## 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)
- Welcome
- fzf使用
- git回滚
- 安装gollum使用github作为wiki端
- 使用github的issue
- linux的脚本
- git冲突解决
- sphinx生成python文档
- 使用aria2作为下载客户端
- tmux使用
- anaconda的虚拟环境构建
- git commit message
- tensorflow指定GPU,限制显存
- pycharm professional
- 好用的命令行工具
- lrzsz使用
- 使用iTerm2的profile免密登陆远程主机
- quicklook 插件
- docker基本使用
- jupyter notebook转html和pdf
- jupyter-notebook几个有用命令
- mongodb安装
- pytorch载入与训练模型
- git覆盖分支
- Jetson TX2资源
- GitHub上fork的repo和上游分支保持一致的方法
- vscode调试前端代码
- github hosts
- git添加远程仓库
- 其它语言好用的库/包
- git强制拉取和强制提交
- chrome扩展发布
- mac的CPP lib
- vscode远程