Docker教程精要版

docker的应用场景(作用)

首先是名字解释:
环境:比如运行一个软件,需要安redis、mysql、nginx、jdk才能用,这些就叫环境。
运维:一般来说,开发只负责写代码,运维负责把代码部署到众多机器上(光代码不行 还得有环境)

避免重复弄环境!(比如安软件、映射端口、文件夹设置、权限分配等),有的环境安错了甚至要重装系统,费时费力
1、避免换机器或者重置系统的时候 重复配置环境 快速部署 就像一个“windows镜像”
2、测试环境和线上环境 ,如果改了环境,要重复弄。以及,“我的电脑上可以用,你的为什么就不行”
3、集群多台机器的情况
4、想发给同学试试,那他还得先装各种软件才能用,还不能保证能跑起来,因为别人操作系统可能比较特殊

有了docker后
我们发布代码的时候,不光发布代码,还把环境也带上一起打包发布。
运维这个角色就弱化了 不一样要有。

流程:我们开发代码,然后把运行环境一起打包,变成一个镜像,然后放到仓库中,之后不同的机器下载这个镜像,然后运行。

docker图标 集装箱,隔离思想。
之前可能各个应用打架,比如共同占用一个端口,矛盾。而且可能一个崩溃了影响另一个。
而docker隔离后,一个在隔离的箱子中坏了不影响另一个
而且你还可以同时安装不同版本的软件,比如python2和python3 互相不影响

快速安装软件,不需要各种“教程”

和虚拟机的不同:
虚拟机要安装整个系统,还得模拟硬件,笨重。比如开两个虚拟机,要模拟两套硬件、开两个系统。而我们其实可能只是运行一个简单的软件,就得单独安个系统 开销太大 划不来。虚拟机会安装很多你不需要的软件!
而容器共享操作系统和硬件资源。模拟的级别仅仅是(软件【如jdk、mysql等】+最核心的系统环境(4MB))。但是有自己的文件存储,互相隔离。容器仅仅会安装你需要的软件。

Docker教程精要版_第1张图片
Docker教程精要版_第2张图片

基本概念介绍

镜像(Image)
容器(Container)
仓库(Repository)

镜像

只读性:Docker 镜像就是一个只读的模板。

例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境、一个mysql运行环境等

静态性:镜像是用来创建 Docker 容器的,是静止的。而容器是运行状态,是动态的。就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
镜像可以理解为安装包,容器理解为打开的软件。

Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

my:简而言之,镜像就像不同的组件,它们彼此相对独立,有的比较大类似程序包,有的小一些只是一个类,有的更小只是一个函数。这些组件是“只读”的,比如我们在写代码的时候,一般不会去改系统函数的底层实现,只是直接拿来用。利用这些组件,能够组装构建出一个应用(容器)。

容器

Docker 利用容器来运行应用。

容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。

可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

*注:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

仓库

仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool 等,可以提供大陆用户更稳定快速的访问。

当然,用户也可以在本地网络内创建一个私有仓库。

当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

注:Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。

Hello world

最简单的容器

# 使用镜像运行容器
$ docker run ubuntu:15.10 /bin/echo "Hello world" #使用镜像进入容器 并使用命令
#以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

启动交互式容器

上面的例子中,只能一次性把所以命令输入,但是很多时候 我们不想或者不能一次性输入所有命令
我们通过 docker 的两个参数 -i -t,让 docker 运行的容器实现"对话"的能力:

$ docker run -i -t ubuntu:15.10 /bin/bash   #可简写为-it
root@0123ce188bd8:/#

-t: 在新容器内指定一个伪终端或终端。

-i: 允许你对容器内的标准输入 (STDIN) 进行交互。

注意第二行 root@0123ce188bd8:/#,此时我们已进入一个 ubuntu15.10 系统的容器
然后 我们在容器内查看文件

root@0123ce188bd8:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@0123ce188bd8:/# 

我们可以使用exit 或者ctr+D 退出容器

后台容器

有时,我们希望退出容器后,容器还在运行,比如使用服务器,可使用-d参数

$ docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"

但是我们不确定容器运行了没,此时可以

docker ps
CONTAINER ID        IMAGE                  COMMAND              ...  
5917eac21c36        ubuntu:15.10           "/bin/sh -c 'while t…"    ...

输出详情介绍:

CONTAINER ID: 容器 ID。

IMAGE: 使用的镜像。

COMMAND: 启动容器时运行的命令。

CREATED: 容器的创建时间。

STATUS: 容器状态。

状态有7种:

created(已创建)
restarting(重启中)
running 或 Up(运行中)
removing(迁移中)
paused(暂停)
exited(停止)
dead(死亡)
PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。

NAMES: 自动分配的容器名称。

在宿主主机内使用 docker logs 命令,查看容器内的标准输出:

$ docker logs 2b1b7a428627
# 会看到一排又一排的hello world
#停止容器
$ docker stop 容器名

命令

sudo docker为固定前缀 之后不再说明了
docker 命令 --help 查看帮助

镜像使用(命令)

#也可网络搜索
docker search 包名
#pull命令 用于从仓库获取需要的镜像  如果不指定版本 下载的就是最新版
sudo docker pull ubuntu:12.04  //从官方镜像仓库获取
sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04  #从指定仓库获取镜像
# 下载的时候 会分层下载! 比如下载mysql5.7 和8  下完5.7再下8的时候 ,有的依赖镜像下载过了 就不会再下载了,但是最终显示的时候 只有一个
# 官方镜像都比较大  我们可以自己做
# 使用镜像运行容器
$ docker run ubuntu:15.10 /bin/echo "Hello world" #使用镜像进入容器 并使用命令
#以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。
#列出镜像
$ docker images
# 第一个参数是来自哪个仓库 第二个参数是指定具体信息 如版本  第三个参数是镜像的唯一身份id 
REPOSITORY       TAG      IMAGE ID      CREATED      VIRTUAL SIZE
ubuntu           12.04    74fe38d11401  4 weeks ago  209.6 MB
ubuntu           precise  74fe38d11401  4 weeks ago  209.6 MB
ubuntu           14.04    99ec81b80c55  4 weeks ago  266 MB
mysql            5.6      f2e8d6c772c0  3 weeks ago  324.6 MB
#修改镜像,先进入容器 修改后 再commit提交(本质是将容器持久化为我们自定义的镜像!)
$ sudo docker run -t -i training/sinatra /bin/bash #使用镜像生成容器
# 干一些事情 比如下载软件 命令省略
$ exit #退出容器
# 提交镜像commit命令  -m是提交的自定义信息 用于提示  -a是指定更新的用户信息;之后是用来创建镜像的容器的 ID;
# 最后的参数是指定目标镜像的仓库名(冒号前)和 tag 信息(冒号后)。创建成功后会返回这个镜像的 ID 信息。
$ sudo docker commit -m "安装了软件" -a "Docker Newbee" 0b2616b0e5a8 ouruser/sinatra:v2

#使用dockerfile创建镜像
$ docker build   # 具体的用到在查
# 从本地文件导入创建镜像
$ docker import
#导出镜像到本地
docker save
#从本地加载镜像(和上面创建不同 这里是直接加载)
docker load

# 移除镜像
# 如果要移除本地的镜像,可以使用 docker rmi 命令。注意 docker rm 命令是移除容器。
# 注意:在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器。

容器的使用

# 启动容器
# 这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
$ docker run -it ubuntu /bin/bash
# -P:将容器内部使用的网络端口随机映射到我们使用的主机上。
docker run -d -P training/webapp 
# 手动设置不一样的端口
docker run -d -p 5000:5000 training/webapp python app.py

# 查看所有容器
docker ps -a  #不带a只会显示运行中的
#启动容器 根据id
$ docker start b750bbbcfd88  
# 进入后台容器!

# 在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
# docker attach
# docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。
#导出容器(快照) docker export
 $ docker export 1e560fca3906 > ubuntu.tar
 # 导入容器(快照) docker import
 $ cat docker/ubuntu.tar | docker import - test/ubuntu:v1
#删除容器
$ docker rm -f 1e560fca3906
# 查看容器内的进程
docker top 容器名

将容器持久化为镜像的看容器那

实例-运行一个python web服务器容器

docker pull training/webapp  # 载入镜像
# 
docker run -d -P training/webapp python app.py #使用刚刚载入的镜像运行进入容器 运行py文件 
docker ps
CONTAINER ID        IMAGE               COMMAND             ...        PORTS                 
d3d5e39ed9d3        training/webapp     "python app.py"     ...        0.0.0.0:32769->5000/tcp
# 前面的是物理机器的端口,里面的是容器内部使用的端口 这样 我们就可以在外部通过32769端口访问容器内的服务器了

Docker教程精要版_第3张图片

其他

windows10可用wsl2(windows 下的linux子系统)去运行docker

推荐

音乐编程学院 https://www.bilibili.com/video/BV1s54y1n7Ev?from=search&seid=11902764066632228605&spm_id_from=333.337.0.0
https://www.bilibili.com/video/BV1og4y1q7M4?p=11&spm_id_from=pageDriver

深入检出!https://zhuanlan.zhihu.com/p/49912239 强烈推荐这个系列

docker的本质 为什么centos才70mb?

https://www.cnblogs.com/Skybiubiu/p/15673175.html

问:Docker 镜像本质是什么?

答:是一个分层文件系统。
Linux文件系统由bootfs和rootfs两部分组成

bootfs:包含bootloader(引导加载程序)和kernel(内核)。
rootfs:root文件系统,包含的就是典型Linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。
不同的Linux发行版,bootfs基本一样,而rootfs不同,如ubuntu和centos等。一个镜像
可以放在另一个镜像的上面,位于下面的镜像称为父镜像,最底部的镜像称为基础镜像。
当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器(可写容器中保存着更改的数据)。

问:Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个G?

答:Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层。

问:Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?

答:由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像所有整个对外暴露的tomcat镜像大小500多MB。

docker文件分层

https://zhuanlan.zhihu.com/p/70424048
可以想象,像 ubuntu等基础镜像,体积必然不小。那么,思考以下几个问题:

我们基于同一个镜像(ubuntu 18.4)启动了两个容器,会占用两倍磁盘空间吗?
我们在容器内修改或者新建了某个文件,要修改原镜像吗?
我们基于某镜像(ubuntu 18.04)新建一个镜像(myubuntu),需要将原镜像文件全部拷贝到新镜像中吗?
首先,让我们尝试思考下,如果我们去做,该如何高效的解决这些问题?

问题 1,只要将同一个镜像文件加载到内存不同位置就行了,没必要在磁盘上存储多份,可以节省大量存储空间。
问题 2,我们可以参考 Linux 内核管理内存的 Copy-On-Write 策略,也即读时大家共用一份文件,如果需要修改再复制一份进行修改,而大部分文件是其实不会修改的,这样可以最大限度节省空间,提升性能。
问题 3,我们可以将镜像文件分为多个独立的层,然后新镜像文件只要引用基础镜像文件就可以了,这样可以节省大量空间。至于修改基础镜像文件的情况,参考问题 2 。
如果你能想到以上思路,那么恭喜你,因为 Docker 就是这么做的,你已经具备为写docker 写一套文件系统的实力了(哈哈哈哈,不要飘,还有大量技术细节需要思考)。
Docker教程精要版_第4张图片
事实上,容器(container)和镜像(image)的最主要区别就是容器加上了顶层的读写层。所有对容器的修改都发生在此层,镜像并不会被修改,也即前面说的 COW(copy-on-write)技术。容器需要读取某个文件时,直接从底部只读层去读即可,而如果需要修改某文件,则将该文件拷贝到顶部读写层进行修改,只读层保持不变。

每个容器都有自己的读写层,因此多个容器可以使用同一个镜像,另外容器被删除时,其对应的读写层也会被删除(如果你希望多个容器共享或者持久化数据,可以使用 Docker volume)。

最后,执行命令 docker ps -s,可以看到最后有两列 size 和 virtual size。其中 size就是容器读写层占用的磁盘空间,而 virtual size 就是读写层加上对应只读层所占用的磁盘空间。如果两个容器是从同一个镜像创建,那么只读层就是 100%共享,即使不是从同一镜像创建,其镜像仍然可能共享部分只读层(如一个镜像是基于另一个创建)。因此,docker 实际占用的磁盘空间远远小于 virtual size 的总和。

commit export save的区别

https://zhuanlan.zhihu.com/p/152219012

commit用于对外发行的,特别是软件安装的包,可以分层下载。
export和save则更适合数据层或者纯自己的代码 不打算分享出去的。而数据其实更适合volume
一个会保留之前的记录,一个只记录现在的状态(没分层了)
Docker教程精要版_第5张图片
Docker教程精要版_第6张图片

你可能感兴趣的:(代码,docker,容器,运维)