【docker】 Docker 基础

Docker 是流行的开源应用容器引擎,本文介绍 docker 的概念以及何如使用。

Docker 镜像

Docker 镜像类似于虚拟机的镜像,可以将它理解为一个只读的模板。

镜像管理

镜像由【镜像名+Tag】指定,Tag 通常用版本来表示,例如 ubuntu:14.04。 如果 Tag 不指定,就默认使用 latest 标签,表示最新版本的镜像。

获取镜像

1
2
# 这个命令将从 Docker Hub 下载指定的镜像
docker pull ${IMAGE_NAME}[:${TAG}]

查看镜像信息

1
2
# 列出本地主机上已有镜像的基本信息,其中的 IMAGE ID 唯一标识了镜像
docker images

给镜像添加标签

1
2
# 创建一个镜像 ${NEW_IMAGE_NAME}[:${NEW_TAG}],新镜像实际上指向旧的镜像
docker tag ${IMAGE_NAME}[:${TAG}] ${NEW_IMAGE_NAME}[:${NEW_TAG}]

查看镜像/容器的详细信息

1
docker inspect ${IMAGE_NAME}[:${TAG}]

查看镜像的历史

1
docker history ${IMAGE_NAME}[:${TAG}]

搜索镜像

1
2
# 在远端仓库搜索指定的镜像
docker search ${PATTERN}

删除镜像

1
2
3
docker rmi ${IMAGE_NAME}[:${TAG}]

docker rmi [ -f ] ${IMAGE_ID}

注:如果有该镜像创建的容器时,镜像文件默认无法删除,除非用 -f 强制删除

导入 & 导出镜像

1
2
3
4
5
6
7
# 将镜像导出到文件
docker save -o ${FILE_NAME} ${IMAGE_NAME}[:${TAG}]

# 将文件导入到本地镜像库
docker load --input ${FILE_NAME}

docker < ${FILE_NAME}

上传镜像

1
docker push ${USER_NAME}/${IMAGE_NAME}[:${TAG}]

镜像制作

镜像制作有 3 种方式:基于已有镜像的容器创建;基于本地模板导入;基于 Dockerfile 创建

基于已有镜像的容器创建

1
2
# 根据容器 CONTAINER_ID 创建一个镜像
docker commit ${CONTAINER_ID} ${IMAGE_NAME}[:${TAG}]

基于本地模板导入

1
2
3
# 从文件、URL 或标准输入读取信息并创建一个镜像
# 可以使用网站提供的标准模板,也可以使用其他已导出的镜像模板来创建。
docker import ${FILE} | ${URL} | - ${IMAGE_NAME}[:${TAG}]
1
2
# 将容器导出到文件
docker export -o ${FILE_NAME} ${CONTAINER}

使用 Dockerfile 创建

Docker 容器

Docker 容器类似于一个轻量级的沙箱,用来运行和隔离应用。容器是从镜像创建的应用运行实例,可以将其启动,开始,停止,删除,而容器彼此间是相互隔离的。

容器管理

容器的创建与启动

1
2
# 根据指定的镜像创建一个容器,容器处于停止状态
docker create ${IMAGE_NAME}[:${TAG}]
1
2
# 启动一个容器
docker start ${CONTAINER}
1
2
# 等价于 start 与 run 的组合,创建并启动一个容器
docker run ${IMAGE_NAME}[:${TAG}]

用 run 创建容器时, docker 在后台运行这些操作

  1. 检查宿主是否有指定的镜像,没有就从仓库下载
  2. 利用镜像创建容器,并启动
  3. 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中
  5. 从网桥的地址池配置一个 IP 地址给容器
  6. 执行用户指定的应用程序(run 命令指定的应用程序)

与容器交互

run 命令中
-i 选项可以保持标准输入打开
-t 选项可以分配一个伪终端(-it 一般一起使用)
-d 选项使容器在后台运行
–name=”” 指定容器别名,方便引用

1
2
# 查看容器中标准输出所输出的信息
docker logs ${CONTAINER}
1
2
# 进入容器
docker attach ${CONTAINER}
1
2
3
# 在容器中执行命令,可以执行 /bin/bash 来进入容器并进行操作
# 同 run 命令一样, 可以带 -it 选项
docker exec ${CONTAINER} ${COMMAND}

容器网络设定

通过 p 参数可以设定网卡和端口映射,可以用 -P 随机映射端口

1
docker run -d -p 8080:8080 ${IMAGE}

通过 name 参数可以设定容器的名字,之后可以通过 link 参数让容器连接

1
2
3
4
5
6

# 创建一个名为 db 的容器
docker run -d --name db ${IMAGE}

# 创建一个名为 web 的容器,跟 db 连接
docker run -d -P --name web --link db:db ${IMAGE}

使用 link 后,Docker 相当于在两个互联的容器之间创建了一个虚拟通道,这样 db 就不用映射它的端口到宿主。在 web 容器中,会有环境变量带入 db 中相关的变量,例如端口,协议。同时 web 容器的 /etc/host 会有 db 的 IP。

存储

docker 中数据有两种方式管理

  1. 数据卷: 容器内数据映射到宿主环境
  2. 数据卷容器: 使用特定的容器维护数据卷

数据卷

数据卷是一个可以供容器使用的特殊目录,将宿主的目录直接映射进容器,类似于 linux 中的 mount。数据卷和镜像是
解耦的,数据的更新不会影响到镜像(例如 commit 不包含数据)

使用 run 命令的 -v 选项可以创建一个或多个数据卷,也可以映射到宿主的目录

1
2
3
4
5
6
7
8
9
# 创建一个数据卷并挂载到容器的 CONTAINER_DIR 目录
docker run -v ${CONTAINER_DIR} ${IMAGE}

# 例如,创建一个容器
docker run --name dbvolumn -it -v /dbdata busybox
# 进入容器,用 mount 查看加载点
mount | grep dbdata
# 输出
/dev/mapper/centos-root on /dbdata type xfs (rw,seclabel,relatime,attr2,inode64,noquota)
1
2
# 加载宿主的目录到容器的指定目录
docker run -v ${HOST_DIR}:${CONTAINER_DIR} ${IMAGE}

数据卷容器

数据卷容器也是容器,它的作用就是专门用来存放数据(注:数据卷容器的使用时,并不需要在运行状态)

首先,创建一个带有数据卷的容器

1
docker run -it -v ${CONTAINER_DIR} --name dbdata ${IMAGE}

然后可以在其他容器中挂载 dbdata 容器中的数据卷

1
2
3
4
# 容器 db1, db2 都使用了同一个数据卷, 3 个容器任何一方在该目录写入的数据
# 在其他容器都可以看到
docker run -it --volumns-from dbdata --name db1 ${IMAGE}
docker run -it --volumns-from dbdata --name db2 ${IMAGE}