0%

docker学习笔记

镜像

获取镜像

Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker 会从镜像仓库下载(默认是 Docker Hub 公共注册服务器中的仓库)。

下载镜像:

1
2
3
docker pull image:tag
# 相当于
docker pull registry.hub.docker.com/image:tag

列出镜像:

1
docker images

创建镜像

修改已有镜像

  1. 使用本地镜像启动容器: docker run -i -t ubuntu:12.04 /bin/bash
  2. 修改
  3. 提交: docker commit -m=”msg” -a=”author” container_id rep/name:tag

提交参数:

  • -m:提交的描述信息
  • -a:指定镜像作者
  • e218edb10161:容器ID
  • runoob/ubuntu:v2:指定要创建的目标镜像名

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
FROM    centos:6.7
MAINTAINER Fisher "fisher@sudops.com"

RUN /bin/echo 'root:123456' |chpasswd
RUN useradd runoob
RUN /bin/echo 'runoob:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
ADD myApp /var/www
EXPOSE 80
CMD /usr/sbin/sshd -D
  • 使用#注释
  • 每一个指令都会在镜像上创建一个新的层,每一个指令的前缀必须大写
  • 一个镜像不能超过 127 层
  • 第一条FROM指令指定使用哪个镜像源
  • MAINTAINER 表示维护者的信息
  • RUN 指令表示在镜像内执行的命令
  • ADD 命令复制本地文件到镜像
  • EXPOSE 命令向外部开放端口
  • CMD 命令描述容器启动后运行的程序
  • 最后通过docker build命令来构建一个镜像
1
2
3
# -t 添加 tag
# dir 是 Dockerfile 所在的路径
docker build -t runoob/centos:6.7 dir

本地文件系统导入

1
cat ubuntu-14.04-x86_64-minimal.tar.gz  |docker import - ubuntu:14.04

上传镜像

  • 登录: docker login -u user -p passwd -e email hub.c.163.com(网易蜂巢)
  • 标签: docker tag image user_name/repo_name[:tag]
  • 上传: docker push hub.c.163.com/user_name/repo_name[:tag]

导出与导入

1
2
3
4
5
6
# 导出镜像到本地文件
docker save -o file_name image:tag
# 载入镜像
docker load --input file_name
#
docker load < file_name

移除

1
docker rmi name/id

容器

基本操作

1
2
3
4
5
6
7
8
# 运行容器
docker run image:tag cmd
# 交互式运行容器
docker run -i -t image:tag cmd
# 停止容器
docker stop id/name
# 重启容器
docket stop id/name
  • -t: 在新容器内指定一个伪终端或终端
  • -i: 允许对容器内的标准输入 (STDIN) 进行交互
  • -d: 后台启动一个容器
  • -p local_port:container_port: 端口映射

进入容器

attach

1
docker attach name/id

nsenter

删除

1
docker rm name/id

数据管理

数据卷

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用
  • 数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 加载一个数据卷到容器的 /webapp 目录
# 也可以在 Dockerfile 中使用 VOLUME 来添加一个或者多个新的卷到由该镜像创建的任意容器
docker run -d -P --name web -v /webapp training/webapp python app.py

# 指定挂载一个本地主机目录到容器中
# 加载主机的 /src/webapp 目录到容器的 /opt/webapp 目录, 如果目录不存在会自动创建
# Dockerfile 中不支持这种用法,因为不同操作系统的路径格式不一样
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

# 挂载数据卷的默认权限是读写,可以通过 :ro 指定为只读
docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

# 挂载一个本地主机文件作为数据卷
docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

数据卷容器

如果有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。

  1. 创建一个命名的数据卷容器dbdata:
1
docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres
  1. 在其他容器中使用 –volumes-from 来挂载 dbdata 容器中的数据卷
1
2
3
4
5
docker run -d --volumes-from dbdata --name db1 training/postgres
docker run -d --volumes-from dbdata --name db2 training/postgres
# 可以使用多个 --volumes-from 参数来从多个容器挂载多个数据卷,也可以从其他已经挂载了数据卷的容器来挂载数据卷。
# 使用 --volumes-from 参数所挂载数据卷的容器自己并不需要保持在运行状态
docker run -d --name db3 --volumes-from db1 training/postgres

如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用 docker rm -v 命令来指定同时删除关联的容器。

备份、恢复、迁移数据卷

备份

首先使用 –volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:

1
docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

容器启动后,使用了 tar 命令来将 dbdata 卷备份为本地的 /backup/backup.tar。

恢复

如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 dbdata2。

1
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar 解压备份文件到挂载的容器卷中。

1
docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

网络

外部访问容器

  • 当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
  • -p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort。

映射所有接口地址:

  • docker run -d -p 5000:5000 training/webapp python app.py: 默认会绑定本地所有接口上的所有地址。

映射到指定地址的指定端口:

  • 使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址

映射到指定地址的任意端口:

  • 使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。

还可以使用 udp 标记来指定 udp 端口:

  • docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py

查看映射端口配置:

  • 使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址:port nostalgic_morse 5000

容器互联

容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式。该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。

自定义容器命名

连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。使用 –name 标记可以为容器自定义命名。

1
docker run -d -P --name web training/webapp python app.py

在执行 docker run 的时候如果添加 –rm 标记,则容器在终止后会立刻删除。注意,–rm 和 -d 参数不能同时使用。

容器互联

使用 –link 参数可以让容器之间安全的进行交互。–link 参数的格式为 –link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。

1
2
3
4
5
6
7
8
9
10
# 创建一个新的数据库容器。
docker run -d --name db training/postgres
# 创建一个新的 web 容器,并将它连接到 db 容器
docker run -d -P --name web --link db:db training/webapp python app.py
# docker ps 查看容器的连接
docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
349169744e49 training/postgres:latest su postgres -c '/usr About a minute ago Up About a minute 5432/tcp db, web/db
aed84ee21bde training/webapp:latest python app.py 16 hours ago Up 2 minutes 0.0.0.0:49154->5000/tcp web

可以看到自定义命名的容器,db 和 web,db 容器的 names 列有 db 也有 web/db。这表示 web 容器链接到 db 容器,web 容器将被允许访问 db 容器的信息。Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动 db 容器的时候并没有使用 -p 和 -P 标记,从而避免了暴露数据库端口到外部网络上。

Docker 通过 2 种方式为容器公开连接信息:

  1. 环境变量
  2. 更新 /etc/hosts 文件

使用 env 命令来查看 web 容器的环境变量:

1
2
3
4
5
6
7
8
9
$ sudo docker run --rm --name web2 --link db:db training/webapp env

DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5000_TCP=tcp://172.17.0.5:5432
DB_PORT_5000_TCP_PROTO=tcp
DB_PORT_5000_TCP_PORT=5432
DB_PORT_5000_TCP_ADDR=172.17.0.5
# 其中 DB_ 开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。

除了环境变量,Docker 还添加 host 信息到父容器的 /etc/hosts 的文件。下面是父容器 web 的 hosts 文件

1
2
3
4
5
docker run -t -i --rm --link db:db training/webapp /bin/bash
root@aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7 aed84ee21bde
. . .
172.17.0.5 db

这里有两个 hosts,第一个是 web 容器,web 容器用 id 作为他的主机名,第二个是 db 容器的 ip 和主机名。可以在 web 容器中安装 ping 命令来测试跟db容器的连通。