🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 1.概念 Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 开始,则进一步演进为使用 runC 和 containerd。 Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。 ### Docker 镜像 我们都知道,操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu 16.04 最小系统的 root 文件系统。 Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 ### Docker 容器 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。 按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。 ### Docker仓库 一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。 通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。 以 Ubuntu 镜像 为例,ubuntu 是仓库的名字,其内包含有不同的版本标签,如,14.04, 16.04。我们可以通过 ubuntu:14.04,或者 ubuntu:16.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu,那将视为 ubuntu:latest。 仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。 国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如: Docker 官方提供的中国 registry mirror https://registry.docker-cn.com 七牛云加速器 https://reg-mirror.qiniu.com/ 当配置某一个加速器地址之后,若发现拉取不到镜像,请切换到另一个加速器地址。 国内各大云服务商均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。 ## 2.使用镜像 `pull`: 拉取镜像 ```sh docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] ``` `images`: 列出镜像 ```sh docker images ``` ``` REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 5f515359c7f8 5 days ago 183 MB nginx latest 05a60462f8ba 5 days ago 181 MB mongo 3.2 fe9198c04d62 5 days ago 342 MB <none> <none> 00285df0df87 5 days ago 342 MB ubuntu 16.04 f753707788c5 4 weeks ago 127 MB ubuntu latest f753707788c5 4 weeks ago 127 MB ubuntu 14.04 1e0c3dd64ccd 4 weeks ago 188 MB ``` `rmi`:删除镜像 ```sh docker rmi [选项] <镜像1> [<镜像2> ...] ``` 其中,<镜像> 可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要. ## 3.操作容器 `run` ```sh docker run -it -d --privileged --runtime=nvidia --name test <镜像> ``` 其中,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。如果在docker run后面追加-d,那么容器将会运行在后台模式。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。默认情况下,Docker的容器是没有特权的,例如不能在容器中再启动一个容器。这是因为默认情况下容器是不能访问任何其它设备的。但是通过"--privileged",容器就拥有了访问任何其它设备的权限。 当操作者执行docker run --privileged时,Docker将拥有访问主机所有设备的权限,同时Docker也会在apparmor或者selinux做一些设置,使容器可以容易的访问那些运行在容器外部的设备。--runtime=nvidia启动GPU运行时。--name设置名称。 `ps -as`: 列出运行中的容器。 `stop`: 终止容器 `restart` :重启容器 `start`:启动一个或多个已经被停止的容器 `rm`:删除容器 ```sh docker rm [选项] <容器1> [<容器2> ...] ``` `exec`: 进入容器 ```sh docker exec -it {{容器id}} /bin/bash ``` 退出容器使用`exit` ## 4.外部数据 #### 挂载目录 ```sh docker run -it -d --privileged --name test \ # -v /home/dev/test:/home/dev/test \ --mount type=bind,source=/home/dev/test,target=/home/dev/test \ {镜像} ``` 本地目录的路径必须是绝对路径,使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,使用 --mount 参数时如果本地目录不存在,Docker 会报错。 #### 外部访问容器 容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。 当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。 使用 docker container ls 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。 ```sh docker run -d -P training/webapp python app.py ``` ```sh docker container ls -l ``` ``` CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp nostalgic_morse ``` -p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有` ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort`。 ## 5.push镜像 #### Docker一共有两种构建镜像的方法(都是基于基础镜像构建新的镜像,用户当然也可以一步一步构建自己的镜像) * 使用docker commit构建 * 使用docker build和Dockerfile命令构建 #### 使用docker commit创建一个新的镜像 * 1.运行一个基础镜像,生成一个基础的容器 ~~~ sudo docker run -t -i ubuntu /bin/bash ~~~ * 2.在运行的容器中进行修改,安装需要的软件并进行配置 添加阿里云镜像站,`vim /etc/apt/sources.list` ``` deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse ``` `sudo apt-get update` 之后就可以安装软件,注意由于安装的系统版本不同,所以各有问题,例如opencv-python的安装可能就会使用`sudo apt-get install python-opencv` 安装软件。 * 3.使用exit命令退出容器 ~~~ exit ~~~ * 4.使用docker commit命令生成一个新的镜像 ~~~ sudo docker commit 容器id 目标镜像仓库/镜像名 ~~~ 使用dockerfile构建: 写好dockerfile之后,使用`docker build --rm -t [name]:[tag]` push到阿里云: [https://www.cnblogs.com/afangxin/p/6601099.html](https://www.cnblogs.com/afangxin/p/6601099.html) [https://www.jianshu.com/p/93a678d1bde6](https://www.jianshu.com/p/93a678d1bde6) ## 6.容器协同 [http://c.biancheng.net/view/3166.html](http://c.biancheng.net/view/3166.html) [https://blog.csdn.net/u013091013/article/details/70208178](https://blog.csdn.net/u013091013/article/details/70208178) >参考: [Docker——入门到实践](https://legacy.gitbook.com/book/yeasy/docker_practice)