Docker命令概要

常用的Docker命令有以下一些1 2 3

1. docker version

显示 Docker 版本信息。

2. docker info

显示 Docker 系统信息,包括镜像和容器数。

3. docker search

1
2
docker search [options "o">] term
docker search -s django

从 Docker Hub 中搜索符合条件的镜像。

--automated 只列出 automated build类型的镜像;

--no-trunc 可显示完整的镜像描述;

-s 40 列出收藏数不小于40的镜像。

4. docker pull

1
2
docker pull [-a "o">] [user/ "o">]name[:tag "o">]
docker pull laozhu/telescope:latest

从 Docker Hub 中拉取或者更新指定镜像。

-a 拉取所有 tagged 镜像 。

5. docker login

1
2
3
4
5
root@moon:~# docker login
Username: username
Password: ****
Email: user@domain.com
Login Succeeded

按步骤输入在 Docker Hub 注册的用户名、密码和邮箱即可完成登录。

6. docker logout

运行后从指定服务器登出,默认为官方服务器。

7. docker images

1
docker images [options "o">] [name]

列出本地所有镜像。其中 [name] 对镜像名称进行关键词查询。

-a 列出所有镜像(含过程镜像);

-f 过滤镜像,如: -f ['dangling=true'] 只列出满足dangling=true 条件的镜像;

--no-trunc 可显示完整的镜像ID;

-q 仅列出镜像ID。

--tree 以树状结构列出镜像的所有提交历史。

8. docker ps

列出所有运行中容器。

-a 列出所有容器(含沉睡镜像);

--before="nginx" 列出在某一容器之前创建的容器,接受容器名称和ID作为参数;

--since="nginx" 列出在某一容器之后创建的容器,接受容器名称和ID作为参数;

-f [exited=] 列出满足exited= 条件的容器;

-l 仅列出最新创建的一个容器;

--no-trunc 显示完整的容器ID;

-n=4 列出最近创建的4个容器;

-q 仅列出容器ID;

-s 显示容器大小。

9. docker rmi

1
2
docker rmi [options "o">] <image> "o">[image...]
docker rmi nginx:latest postgres:latest python:latest

从本地移除一个或多个指定的镜像。

-f 强行移除该镜像,即使其正被使用;

--no-prune 不移除该镜像的过程镜像,默认移除。

10. docker rm

1
2
3
docker rm [options "o">] <container> "o">[container...]
docker rm nginx-01 nginx-02 db-01 db-02
sudo docker rm -l /webapp/redis

-f 强行移除该容器,即使其正在运行;

-l 移除容器间的网络连接,而非容器本身;

-v 移除与容器关联的空间。

11. docker history

1
docker history "o">[options] <image>

查看指定镜像的创建历史。

--no-trunc 显示完整的提交记录;

-q 仅列出提交记录ID。

12. docker start|stop|restart

1
docker start|stop "p">|restart [options "o">] <container> "o">[container...]

启动、停止和重启一个或多个指定容器。

-a 待完成

-i 启动一个容器并进入交互模式;

-t 10 停止或者重启容器的超时时间(秒),超时后系统将杀死进程。

13. docker kill

1
docker kill "o">[options "o">] <container> "o">[container...]

杀死一个或多个指定容器进程。

-s "KILL" 自定义发送至容器的信号。

14. docker events

1
2
3
docker events [options "o">]
docker events --since= "s2">"20141020"
docker events --until= "s2">"20120310"

从服务器拉取个人动态,可选择时间区间。

15. docker save

1
2
docker save -i "debian.tar"
docker save > "debian.tar"

将指定镜像保存成 tar 归档文件, docker load 的逆操作。保存后再加载(saved-loaded)的镜像不会丢失提交历史和层,可以回滚。

-o "debian.tar" 指定保存的镜像归档。

16. docker load

1
2
3
docker load [options]
docker load < debian.tar
docker load -i "debian.tar"

从 tar 镜像归档中载入镜像, docker save 的逆操作。保存后再加载(saved-loaded)的镜像不会丢失提交历史和层,可以回滚。

-i "debian.tar" 指定载入的镜像归档。

17. docker export

1
2
docker export <container>
docker export nginx-01 > export.tar

将指定的容器保存成 tar 归档文件, docker import 的逆操作。导出后导入(exported-imported))的容器会丢失所有的提交历史,无法回滚。

18. docker import

1
2
3
docker import url|- "o">[repository[:tag "o">]]
cat export.tar "p">| docker import - imported-nginx:latest
docker import http://example.com/export.tar

从归档文件(支持远程文件)创建一个镜像, export 的逆操作,可为导入镜像打上标签。导出后导入(exported-imported))的容器会丢失所有的提交历史,无法回滚。

19. docker top

1
docker top <running_container> "o">[ps options]

查看一个正在运行容器进程,支持 ps 命令参数。

20. docker inspect

1
2
docker instpect nginx:latest
docker inspect nginx-container

检查镜像或者容器的参数,默认返回 JSON 格式。

-f 指定返回值的模板文件。

21. docker pause

暂停某一容器的所有进程。

22. docker unpause

1
docker unpause <container>

恢复某一容器的所有进程。

23. docker tag

1
docker tag [options "o">] <image>[:tag "o">] [repository/ "o">][username/]name "o">[:tag]

标记本地镜像,将其归入某一仓库。

-f 覆盖已有标记。

24. docker push

1
2
docker push name[:tag "o">]
docker push laozhu/nginx:latest

将镜像推送至远程仓库,默认为 Docker Hub 。

25. docker logs

1
2
docker logs [options "o">] <container>
docker logs -f -t --tail= "s2">"10" insane_babbage

获取容器运行时的输出日志。

-f 跟踪容器日志的最近更新;

-t 显示容器日志的时间戳;

--tail="10" 仅列出最新10条容器日志。

26. docker run

1
docker run [options "o">] <image> [ "nb">command] "o">[arg...]

启动一个容器,在其中运行指定命令。

-a stdin 指定标准输入输出内容类型,可选 STDIN/STDOUT / STDERR 三项;

-d 后台运行容器,并返回容器ID;

-i 以交互模式运行容器,通常与 -t 同时使用;

-t 为容器重新分配一个伪输入终端,通常与 -i 同时使用;

--name="nginx-lb" 为容器指定一个名称;

--dns 8.8.8.8 指定容器使用的DNS服务器,默认和宿主一致;

--dns-search example.com 指定容器DNS搜索域名,默认和宿主一致;

-h "mars" 指定容器的hostname;

-e username="ritchie" 设置环境变量;

--env-file=[] 从指定文件读入环境变量;

--cpuset="0-2" or --cpuset="0,1,2" 绑定容器到指定CPU运行;

-c 待完成

-m 待完成

--net="bridge" 指定容器的网络连接类型,支持 bridge /host / none/container: 四种类型;

--link=[] 待完成

--expose=[] 待完成

详解docker run命令

docker run应该是Docker中最常用的命令了,Docker的官方文档也给予了非常详细的介绍4 5

Docker在执行时会将相关进程封装到相互隔离的容器(container)中。当执行 docker run时,Docker会启动一个进程,同时给这个进程分配其独占的文件系统,独占的网络资源和以此进程为根进程的进程组。在Docker启动container时加载的Image,或许已经定义好了默认的启动进程,需要exposer的网络端口和其他在Dockerfile中定义好的资源。但使用docker run 都可以重新对这个image进行默认定义。这就是为什么run命令参数比docker其他命令参数都多的原因。

基本形式

最基本的docker run命令是如下格式:

1
$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]

如果需要查看[OPTIONS]的详细使用说明,请参考Docker关于OPTIONS的说明。这里仅简要介绍Run所使用到的参数。

OPTIONS总起来说分为两类:

1. 设定操作执行方式:
    1. 决定container的运行方式,前台执行还是后台执行
    2. 设定containerID
    3. 设定network参数
    4. 设定container的CPU和Memory参数
    5. 设定权限(Privileges )和LXC参数
2. 设定image的默认资源,也就是image使用者可以用此命令来覆盖image开发者在build阶段所设定的默认值。

docker run [OPTIONS]可以让image使用者完全控制container的生命周期,允许image使用者覆盖所有image开发者在执行docker build时所设定的参数,甚至也可以修改本身由Docker所控制的内核级参数。

Operator exclusive options

当执行docker run时可以设定的资源如下:

*Detached vs Foreground
*Container Identification
*IPC Setting
*Network Settings
*Clean Up (--rm)
*Runtime Constraints on CPU and Memory
*Runtime Privilege, Linux Capabilities, and LXC Configuration

我们依次进行介绍。

Detached vs foreground

当我们启动一个container时,首先需要确定这个container是运行在前台模式还是运行在后台模式。

1
-d=false: Detached mode: Run container in the background, print new container id

Detached (-d)

如果在docker run 后面追加-d=true或者-d,则containter将会运行在后台模式(Detached mode)。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。因为container不再监听你执行docker run的这个终端命令行窗口。但你可以通过执行docker attach 来重新挂载这个container里面。需要注意的时,如果你选择执行-d使container进入后台模式,那么将无法配合"--rm"参数

Foregroud

如果在docker run后面没有追加-d参数,则container将默认进入前台模式(Foregroud mode)。Docker会启动这个container,同时将当前的命令行窗口挂载到container的标准输入,标准输出和标准错误中。也就是container中所有的输出,你都可以再当前窗口中查看到。甚至docker可以虚拟出一个TTY窗口,来执行信号中断。这一切都是可以配置的:

1
2
3
4
-a=[]      : Attach to `STDIN`, `STDOUT` and/or `STDERR`
-t=false    : Allocate a pseudo-tty
--sig-proxy=true : Proxify all received signal to the process (non-TTY mode only)
-i=false    : Keep STDIN open even if not attached

如果在执行run命令时没有指定-a,那么docker默认会挂载所有标准数据流,包括输入输出和错误。你可以特别指定挂载哪个标准流。

1
$ sudo docker run -a stdin -a stdout -i -t ubuntu /bin/bash (只挂载标准输入输出)

对于执行容器内的交互式操作,例如shell脚本。我们必须使用 -i -t来申请一个控制台同容器进行数据交互。但是当通过管道同容器进行交互时,就不能使用-t. 例如这个命令echo test | docker run -i busybox cat

Container identification

Name (--name)

给container命名有三种方式:

  1. 使用UUID长命名("f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778")   2. 使用UUID短命令("f78375b1c487")   3. 使用Name("evil_ptolemy")

这个UUID标示是由Docker deamon来生成的。如果你在执行docker run时没有指定 --name,那么deamon会自动生成一个随机数字符串当做UUID。但是对于一个container来说有个name会非常方便,因为你可以当你需要link其它容器时或者其他类似需要区分其它容器时,使用容器名称会简化操作。无论container运行在前台或者后台,这个名字都是有效的。

PID equivalent

当你在运行docker时有自动化的要求,那么你可以要求Docker将containerID 输出到你指定的文件中(PIDfile).这种行为就类似于有些应用程序将自身ID输出到文件中,方便后续脚本操作。

1
--cidfile="": Write the container ID to the file

Image[:tag]

当一个image的名称不足以分辨这个image所代表的含义时,你可以在命令中通过添加image[:tag]来指定特定版本的image以运行容器。例如: docker run ubuntu:14.04

IPC Settings

默认情况下,所有容器都开启了IPC命名空间。

1
2
3
--ipc="" : Set the IPC mode for the container,
'container:<name|id>': reuses another container's IPC namespace
'host': use the host's IPC namespace inside the container

IPC(POSIX/SysV IPC)命名空间提供了相互隔离的命名共享内存,信号灯变量和消息队列。

共享内存可以提高进程数据交互速度。共享内存一般用在database和高性能应用(C/OpenMPI, C++/using boost libraries)上或者金融服务上。如果需要容器里面部署上述类型的应用,那么就应该在多个容器直接采取共享内存了。

Network settings

默认情况下,所有的container都开启了网络接口,同时可以接受任何外部的数据请求。

1
2
3
4
5
6
7
8
--dns=[] : Set custom dns servers for the container
--net="bridge" : Set the Network mode for the container
'bridge': creates a new network stack for the container on the docker bridge
'none': no networking for this container
'container:<name|id>': reuses another container network stack
'host': use the host network stack inside the container
--add-host="" : Add a line to /etc/hosts (host:IP)
--mac-address="" : Sets the container's Ethernet device's MAC address

可以通过docker run --net none 来关闭网络接口,此时将关闭所有网络数据的输入输出。这时,你只能通过STDIN,STDOUT或者files来完成I/O操作了。默认情况下,container使用host的DNS设置。但是你可以通过--dns来覆盖container内的dns设置。同时docker会对containter默认生成一个MAC地址,你可以通过--mac-address 12:34:56:78:9a:bc 来设置你自己的mac地址。

以下是网络设置中常用的参数:

* none 关闭container内的网络连接
* bridge 通过veth接口来连接contianer 默认选项
* host 允许container使用host的网络堆栈信息。 注意:这种方式将允许container访问host中类似D-BUS之类的系统服务,所以被认为是不安全的。
* container 使用另外一个container的网络堆栈信息。

None:

将网络模式设置为none时,这个container将不允许访问任何外部router。这个container内部只会有一个loopback接口,而且不存在任何可以访问外部网络的router。

Bridge:

Docker默认是将container设置为bridge模式。此时在host上面讲存在一个docker0的网络接口,同时会针对container创建一对veth接口。其中一个veth接口是在host充当网卡桥接作用,另外一个veth接口存在于container的命名空间中,并且指向container的loopback。Docker会自动给这个container分配一个IP,并且将container内的数据通过桥接转发到外部。

Host:

当网络模式设置为host时,这个container将完全共享host的网络堆栈。host所有的网络接口将完全对container开放。container的主机名也会存在于host的hostname中。这时,container所有对外暴露的port和对其它container的link,将完全失效。

Container:

当网络模式设置为Container时,这个container将完全复用另外一个container的网络堆栈。同时使用时这个container的名称必须要符合下面的格式:--net container:.

比如当前有一个绑定了本地地址localhost的redis container。如果另外一个container需要复用这个网络堆栈,则需要如下操作:

1
2
3
$ sudo docker run -d --name redis example/redis --bind 127.0.0.1
$ # use the redis container's network stack to access localhost
$ sudo docker run --rm -ti --net container:redis example/redis-cli -h 127.0.0.1

Managing /etc/hosts

当一个container再启动时,在/etc/hosts文件里面将会存在包括localhost在内的一些hostname信息。我们也可以使用--add-host这个参数来动态添加/etc/hosts里面的数据。

1
2
3
4
5
6
7
8
9
$ /docker run -ti --add-host db-static:86.75.30.9 ubuntu cat /etc/hosts
172.17.0.22 09d03f76bf2c
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
86.75.30.9 db-static

Clean up (--rm)

默认情况下,每个container在退出时,它的文件系统也会保存下来。这样一方面调试会方便些,因为你可以通过查看日志等方式来确定最终状态。另外一方面,你也可以保存container所产生的数据。但是当你仅仅需要短期的运行一个前台container,这些数据同时不需要保留时。你可能就希望docker能在container结束时自动清理其所产生的数据。

这个时候你就需要--rm这个参数了。 注意:--rm 和 -d不能共用!

1
--rm=false: Automatically remove the container when it exits (incompatible with -d)

Security configuration

1
2
3
4
5
6
--security-opt="label:user:USER" : Set the label user for the container
--security-opt="label:role:ROLE" : Set the label role for the container
--security-opt="label:type:TYPE" : Set the label type for the container
--security-opt="label:level:LEVEL" : Set the label level for the container
--security-opt="label:disable" : Turn off label confinement for the container
--secutity-opt="apparmor:PROFILE" : Set the apparmor profile to be applied to the container

你可以通过--security-opt修改container中默认的schema标签。比如说,对于一个MLS系统来说(MLS可能是指Multiple Listing System,本人不确定.),你可以指定MCS/MLS级别。

下面的这些级别将允许多个container共享content。

1
# docker run --security-opt label:level:s0:c100,c200 -i -t fedora bash

如果是MLS系统,则使用下面的命令:

1
# docker run --security-opt label:level:TopSecret -i -t rhel7 bash

使用下面的命令可以在container内禁用安全策略:

1
# docker run --security-opt label:disable -i -t fedora bash

如果你需要在container内执行更为严格的安全策略,那么你可以为这个container指定一个策略替代。比如你可以使用下面的命令来指定container只允许监听apache port

1
# docker run --security-opt label:type:svirt_apache_t -i -t centos bash

注意:此时,在你的host环境中必须存在一个名为svirt_apache_t的安全策略。

Runtime constraints on CPU and memory

下面的参数可以用来调整container内的性能参数。

1
2
-m="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
-c=0 : CPU shares (relative weight)

通过docker run -m 可以很方便的调整container所使用的内存资源。如果host支持swap内存,那么使用-m可以设定比host物理内存还大的值。

同样,通过-c 可以调整container的cpu优先级。默认情况下,所有的container享有相同的cpu优先级和cpu调度周期。但你可以通过Docker来通知内核给予某个或某几个container更多的cpu计算周期。

默认情况下,使用-c或者--cpu-shares 参数值为0,可以赋予当前活动container 1024个cpu共享周期。这个0值可以针对活动的container进行修改来调整不同的cpu循环周期。

比如,我们使用-c或者--cpu-shares =0启动了C0,C1,C2三个container,使用-c/--cpu-shares=512启动了C3.这时,C0,C1,C2可以100%的使用CPU资源(1024),但C3只能使用50%的CPU资源(512)。如果这个host的OS是时序调度类型的,每个CPU时间片是100微秒,那么C0,C1,C2将完全使用掉这100微秒,而C3只能使用50微秒。

Runtime privilege, Linux capabilities, and LXC configuration

1
2
3
4
5
--cap-add: Add Linux capabilities
--cap-drop: Drop Linux capabilities
--privileged=false: Give extended privileges to this container
--device=[]: Allows you to run devices inside the container without the --privileged flag.
--lxc-conf=[]: (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"

默认情况下,Docker的container是没有特权的。例如不能再container里面再启动一个container。这是因为默认情况下container是不能访问任何其他设备的。但是通过"privileged",container就拥有了访问任何其他设备的权限。

当操作者执行docker run --privileged时,Docker将拥有访问host所有设备的权限,同时Docker也会在apparmor或者selinux做一些设置,使container可以容易的访问那些运行在container外部的设备。你可以访问Docker blog来获取更多关于--privileged的用法。

同时,你也可以限制container只能访问一些指定的设备。下面的命令将允许container只访问一些特定设备:

1
$ sudo docker run --device=/dev/snd:/dev/snd ...

默认情况下,container拥有对设备的读,写,创建设备文件的权限。使用:rwm来配合--device,你可以控制这些权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo docker run --device=/dev/sda:/dev/xvdc --rm -it ubuntu fdisk /dev/xvdc
Command (m for help): q
$ sudo docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk /dev/xvdc
You will not be able to write the partition table.
Command (m for help): q
$ sudo docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk /dev/xvdc
crash....
$ sudo docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted

使用--cap-add和--cap-drop,配合--privileged,你可以更细致的控制container。默认使用这两个参数的情况下,container拥有一系列的内核修改权限。这两个参数都支持all值,如果你想让某个container拥有除了MKNOD之外的所有内核权限,那么可以执行下面的命令:

1
$ sudo docker run --cap-add=ALL --cap-drop=MKNOD ...

如果需要修改网络接口数据,那么就建议使用--cap-add=NET_ADMIN,而不是使用--privileged。

1
2
3
$ docker run -t -i --rm ubuntu:14.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
$ docker run -t -i --rm --cap-add=NET_ADMIN ubuntu:14.04 ip link add dummy0 type dummy

如果要挂载一个FUSE文件系统,那么就需要--cap-add和--device了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ docker run --rm -it --cap-add SYS_ADMIN sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fuse: failed to open /dev/fuse: Operation not permitted
$ docker run --rm -it --device /dev/fuse sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fusermount: mount failed: Operation not permitted
$ docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs
# sshfs sven@10.10.10.20:/home/sven /mnt
The authenticity of host '10.10.10.20 (10.10.10.20)' can't be established.
ECDSA key fingerprint is 25:34:85:75:25:b0:17:46:05:19:04:93:b5:dd:5f:c6.
Are you sure you want to continue connecting (yes/no)? yes
sven@10.10.10.20's password:
root@30aa0cfaf1b5:/# ls -la /mnt/src/docker
total 1516
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:08 .
drwxrwxr-x 1 1000 1000 4096 Dec 4 11:46 ..
-rw-rw-r-- 1 1000 1000 16 Oct 8 00:09 .dockerignore
-rwxrwxr-x 1 1000 1000 464 Oct 8 00:09 .drone.yml
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:11 .git
-rw-rw-r-- 1 1000 1000 461 Dec 4 06:08 .gitignore

如果docker启动时选择了lxc-driver,(docker -d --exec-driver=lxc)。那么就可以使用--lxc-conf来设定LXC参数。但需要注意的是,未来host上面的docker deamon有可能不会使用LXC,所以这些参数有可能会包含一些没有实现的配置功能。那么意味着,操作者在操作这些参数时必须要十分熟悉LXC。

特别注意:当你使用--lxc-conf修改container参数后,docker deamon将不再管理这些参数,那么必须由操作者自行进行管理。比如说,你使用--lxc-conf修改了container的IP地址,那么在/etc/hosts里面是不会自动体现的,需要你自行维护。

Overriding Dockerfile image defaults

当开发者使用Dockerfile进行build或者使用commit提交container时,开发人员可以设定一些image默认参数。

这些参数中,有四个是无法被覆盖的:FROM,MAINTAINER,RUN和ADD。其余参数都可以通过docker run进行覆盖。我们将介绍如何对这些参数进行覆盖。

* CMD (Default Command or Options)
* ENTRYPOINT (Default Command to Execute at Runtime)
* EXPOSE (Incoming Ports)
* ENV (Environment Variables)
* VOLUME (Shared Filesystems)
* USER
* WORKDIR

CMD (default command or options)

1
$ sudo docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]

这条命令中的COMMAND部分是可选的。因为这个IMAGE在build时,开发人员可能已经设定了默认执行的command。作为操作人员,你可以使用上面命令中新的command来覆盖旧的command。

如果image中设定了ENTRYPOINT,那么命令中的CMD也可以作为参数追加到ENTRYPOINT中。

ENTRYPOINT (default command to execute at runtime)

1
--entrypoint="": Overwrite the default entrypoint set by the image

这个ENTRYPOINT和COMMAND类似,它指定了当container执行时,需要启动哪些进程。相对COMMAND而言,ENTRYPOINT是比较困难进行覆盖的,这个ENTRYPOINT可以让container设定默认启动行为,所以当container启动时,你可以执行任何一个二进制可执行程序。你也可以通过COMMAND给这个ENTRYPOINT传递参数。但当你需要再container中执行其他进程时,你就可以指定其他ENTRYPOINT了。

下面就是一个例子,container可以在启动时自动执行shell,然后启动其它进程。

1
2
3
4
$ sudo docker run -i -t --entrypoint /bin/bash example/redis
#or two examples of how to pass more parameters to that ENTRYPOINT:
$ sudo docker run -i -t --entrypoint /bin/bash example/redis -c ls -l
$ sudo docker run -i -t --entrypoint /usr/bin/redis-cli example/redis --help

EXPOSE (incoming ports)

Dockefile在网络方面除了提供一个EXPOSE之外,没有提供其它选项。下面这些参数可以覆盖Dockefile的expose默认值:

1
2
3
4
5
6
7
8
--expose=[]: Expose a port or a range of ports from the container
without publishing it to your host
-P=false : Publish all exposed ports to the host interfaces
-p=[] : Publish a container᾿s port to the host (format:
ip:hostPort:containerPort | ip::containerPort |
hostPort:containerPort | containerPort)
(use 'docker port' to see the actual mapping)
--link="" : Add link to another container (name:alias)

--expose可以让container接受外部传入的数据。container内监听的port不需要和外部host的port相同。比如说在container内部,一个HTTP服务监听在80端口,对应外部host的port就可能是49880.

操作人员可以使用--expose,让新的container访问到这个container。具体有三个方式:

  1. 使用-p来启动container。   2. 使用-P来启动container。   3. 使用--link来启动container。

如果使用-p或者-P,那么container会开发部分端口到host,只要对方可以连接到host,就可以连接到container内部。当使用-P时,docker会在host中随机从49153 和65535之间查找一个未被占用的端口绑定到container。你可以使用docker port来查找这个随机绑定端口。

当你使用--link方式时,作为客户端的container可以通过私有网络形式访问到这个container。同时Docker会在客户端的container中设定一些环境变量来记录绑定的IP和PORT。

ENV (环境变量)

Variable Variable
HOME Set based on the value of USER
HOSTNAME The hostname associated with the container
PATH Includes popular directories, such as : /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TERM xterm if the container is allocated a psuedo-TTY

当container启动时,会自动在container中初始化这些变量。

操作人员可以通过-e来设定任意的环境变量。甚至覆盖已经存在的环境变量,或者是在Dockerfile中通过ENV设定的环境变量。

1
2
3
4
5
6
7
8
9
$ sudo docker run -e "deep=purple" --rm ubuntu /bin/bash -c export
declare -x HOME="/"
declare -x HOSTNAME="85bc26a0e200"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x SHLVL="1"
declare -x container="lxc"
declare -x deep="purple"

操作人员可以通过-h来设定hostname。也可以使用"--link name:alias"来设定环境变量,当使用--link后,docker将根据后面提供的IP和PORT信息来连接服务端container。下面就是使用redis的例子:

1
2
3
4
5
6
7
8
9
10
11
12
# Start the service container, named redis-name
$ sudo docker run -d --name redis-name dockerfiles/redis
4241164edf6f5aca5b0e9e4c9eccd899b0b8080c64c0cd26efe02166c73208f3
# The redis-name container exposed port 6379
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4241164edf6f $ dockerfiles/redis:latest /redis-stable/src/re 5 seconds ago Up 4 seconds 6379/tcp redis-name
# Note that there are no public ports exposed since we didn᾿t use -p or -P
$ sudo docker port 4241164edf6f 6379
2014/01/25 00:55:38 Error: No public port '6379' published for 4241164edf6f

你使用--link后,就可以获取到关于Redis Container的相关信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ sudo docker run --rm --link redis-name:redis_alias --entrypoint /bin/bash dockerfiles/redis -c export
declare -x HOME="/"
declare -x HOSTNAME="acda7f7b1cdc"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x REDIS_ALIAS_NAME="/distracted_wright/redis"
declare -x REDIS_ALIAS_PORT="tcp://172.17.0.32:6379"
declare -x REDIS_ALIAS_PORT_6379_TCP="tcp://172.17.0.32:6379"
declare -x REDIS_ALIAS_PORT_6379_TCP_ADDR="172.17.0.32"
declare -x REDIS_ALIAS_PORT_6379_TCP_PORT="6379"
declare -x REDIS_ALIAS_PORT_6379_TCP_PROTO="tcp"
declare -x SHLVL="1"
declare -x container="lxc"
#And we can use that information to connect from another container as a client:
$ sudo docker run -i -t --rm --link redis-name:redis_alias --entrypoint /bin/bash dockerfiles/redis -c '/redis-stable/src/redis-cli -h $REDIS_ALIAS_PORT_6379_TCP_ADDR -p $REDIS_ALIAS_PORT_6379_TCP_PORT'
172.17.0.32:6379>

Docker也会将这个alias的IP地址写入到/etc/hosts文件中。然后你就可以通过别名来访问link后的container。

1
2
$ sudo docker run -d --name servicename busybox sleep 30
$ sudo docker run -i -t --link servicename:servicealias busybox ping -c 1 servicealias

如果你重启了源container(servicename),相关联的container也会同步更新/etc/hosts。

VOLUME (shared filesystems)

1
2
3
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro].
If "container-dir" is missing, then docker creates a new volume.
--volumes-from="": Mount all volumes from the given container(s)

关于volume参数,可以再 Managing data in containers 查看详细说明。需要注意的是开发人员可以在Dockerfile中设定多个volume,但是只能由操作人员设置container直接的volume访问。

USER

container中默认的用户是root。但是开发人员创建新的用户之后,这些新用户也是可以使用的。开发人员可以通过Dockerfile的USER设定默认的用户,操作人员可以通过"-u "来覆盖这些参数。

WORKDIR

container中默认的工作目录是根目录(/)。开发人员可以通过Dockerfile的WORKDIR来设定默认工作目录,操作人员可以通过"-w"来覆盖默认的工作目录。

docker create与docker run的区别

docker create表示新增一个容器,但是并不启动;docker run表示新增一个容器,并启动运行,直到运行结束。参照容器的生命周期6,如下图,

详细来说,docker create只是新增一个容器,并进入容器生命周期中的created状态;而docker run不但新增一个容器,还立刻start并进入running状态,如运行过程中没有被pause或者kill,会一直运行到程序结束,容器进入stopped状态。因此,docker create命令没有-d参数,而docker run有。在docker run中,-d参数表示后台运行容器,而对于docker create来讲,仅仅只创建了容器,容器并未开始运行,因此也不存在所谓后台运行的概念,因此,docker create没有-d参数。

镜像与容器存放的路径

镜像的存放路径可以看我的另一篇文章《Docker入门介绍》中有提到,在/var/lib/docker下。具体细节来说,一些镜像本身信息相关的文件放在./graph下,容器相关的设置,如一些网络(eg,ip、hostname、hosts等)、unix mq、unix共享内存等信息放在./containers下,镜像本身的文件和容器相关的文件都放在该目录下的./aufs/diff目录下。该目录下有很多以镜像id和容器id命名的目录,每个目录下都是镜像与容器本身的文件。

常用docker命令实践

由于docker需要使用root权限,以下命令如无特别说明,均使用root用户执行,运行环境是Ubuntu 14.04 LTS。

搭建docker registry

docker hub是最大的共有docker镜像仓库,但是对公司内部,往往需要自己的私有仓库,这就是docker registry7。搭建registry很简单,只要使用以下命令从docker hub上拉一个镜像下来即可,

1
docker run -d -p 5000:5000 --name registry registry:2

这样,就在本地的5000端口开了一个registry的服务,可以通过localhost、或本机ip来访问该服务。为了访问ip统一,可以通过修改hosts来达到访问一致,例如,在hosts中增加一行,

1
<docker registry ip> reg-server

还需要在docker的配置文件/etc/default/docker中添加参数DOCKER_OPTS="--insecure-registry reg-server:5000",本文使用的是Ubuntu,如果是Centos的话,需要修改/etc/sysconfig/docker

这样,以后就可以通过访问reg-server来访问该registry,如果registry地址发生变化,也只需要修改hosts文件中的地址就能及时适配。registry的使用与docker hub类似,将在后文中介绍。

下载镜像和运行容器

假设我们要运行busybox这个镜像,这是一个最小linux环境的镜像,可以使用docker pull

1
2
3
4
5
6
7
# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
c00ef186408b: Pull complete
ac6a7980c6c2: Pull complete
Digest: sha256:e4f93f6ed15a0cdd342f5aae387886fba0ab98af0a102da6276eaf24d6e6ade0
Status: Downloaded newer image for busybox:latest

使用docker pull的时候,一个命令只能下载一个镜像,但是可以运行多个命令同时下载,这对于需要一次下载多个镜像的情况很有用。

简单的运行其中的某个命令,只要使用docker run即可,

1
2
3
4
# docker run busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=0ac2c8dee5a9
HOME=/root

如果需要后台运行的话,可以使用-d参数,其他docker run的参数可参考上文。

镜像和容器维护

假设当前系统中下载了多个镜像,可以用docker image查看现有镜像,

1
2
3
4
5
6
7
8
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B

这里只列出了最上层的镜像,如果需要查看所有镜像的话,需要-a参数;如果需要查看完整镜像id,需要--no-trunc=true参数;如果只列出镜像id,其他信息不列出的话,需要使用-q参数。

1
2
3
4
5
6
7
8
9
10
# docker images -a -q --no-trunc=true |wc -l
66
# docker images -q --no-trunc=true
a07681abeb6cd68402477f783d994145137146de3911e42b99f605cecb3e138e
5328fdfe9b8e0c5a19a0773f3e29f9002d444f86521f8f61f3fcb8216ad5287a
af28fa31b54b2e45d53e80c5a7cbfd2693f198fdb8ba53d44d8a432832ad1012
ac6a7980c6c2fb4d29e406efb4f9784b3c67e161eb68a97ffb428d07e3e97693
0643f0c7d17d348881b2dab88cfdb57ad86dcf32ea22bd0b2cd0957b6c7ab8c3
975b84d108f1024953937167506c2935a081c8c55ae9e9f7b7deee118605367f

如果需要列出容器,可以使用docker ps,默认情况下列出正在运行的容器。

1
2
3
4
5
6
7
8
9
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker run -d redis redis-server
7d57630f67d10346b2583e7950ce7c55a4225475c5d5a0265682aad83611946d
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d57630f67d1 redis "/entrypoint.sh redis" 11 seconds ago Up 10 seconds 6379/tcp small_torvalds

-a参数可以列出所有容器,包括已退出运行的容器;-s参数可以列出容器的大小,比较有用;--before=--since=参数可以列出在某个容器之前和之后运行的容器,参数值是容器id。docker ps也有-q--no-trunc=true参数,含义与docker images的相同。具体细节如下,

1
2
3
4
5
6
7
8
9
10
11
# docker ps -a -s
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
800f0acc667c tomcat "java -version" 35 seconds ago Exited (0) 34 seconds ago tender_mietner 0 B (virtual 346.2 MB)
39ea34d89ea3 hello-world "/hello" 2 minutes ago Exited (0) 2 minutes ago agitated_blackwell 0 B (virtual 972 B)
7d57630f67d1 redis "/entrypoint.sh redis" 28 minutes ago Up 28 minutes 6379/tcp small_torvalds 0 B (virtual 107.5 MB)
0ac2c8dee5a9 busybox "env" 52 minutes ago Exited (0) 52 minutes ago cocky_ritchie 0 B (virtual 1.113 MB)
# docker ps -a -s --before=800f0acc667c --since=0ac2c8dee5a9
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
39ea34d89ea3 hello-world "/hello" 3 minutes ago Exited (0) 3 minutes ago agitated_blackwell 0 B (virtual 972 B)
7d57630f67d1 redis "/entrypoint.sh redis" 28 minutes ago Up 28 minutes 6379/tcp small_torvalds 0 B (virtual 107.5 MB)

如果想删除容器,可以使用docker rm

1
2
3
4
5
6
7
8
# docker rm 800f0acc667c 39ea34d89ea3
800f0acc667c
39ea34d89ea3
# docker ps -a -s
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
7d57630f67d1 redis "/entrypoint.sh redis" 29 minutes ago Up 29 minutes 6379/tcp small_torvalds 0 B (virtual 107.5 MB)
0ac2c8dee5a9 busybox "env" 54 minutes ago Exited (0) 54 minutes ago cocky_ritchie 0 B (virtual 1.113 MB)

-f参数可以强行删除容器,即使容器在运行。docker rm可以一次输入多个容器id,删除多个容器。

如果需要删除容器,可以使用docker rmi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# docker rmi busybox
Error response from daemon: conflict: unable to remove repository reference "busybox" (must force) - container 0ac2c8dee5a9 is using its referenced image ac6a7980c6c2
Error: failed to remove images: [busybox]
# docker rm 0ac2c8dee5a9
0ac2c8dee5a9
# docker rmi busybox
Untagged: busybox:latest
Deleted: ac6a7980c6c2fb4d29e406efb4f9784b3c67e161eb68a97ffb428d07e3e97693
Deleted: c00ef186408b85d9657e8241f53ccd1e7071f03b3d4b38863b2cdae88845b587
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B

注意:删除容器前,需要先删除所有的镜像,即使该镜像状态是已退出。强制删除,需要使用-f参数,不推荐。

容器操作

多数情况下,我们使用docker run就可以运行一个容器。但是如果希望对容器生命周期加以更细节的控制,可以使用更多的命令。

命令 功能
docker create 创建容器
docker start 启动容器
docker stop 停止容器
docker restart 重启容器
docker kill 杀死容器进程
docker pause 暂停容器进程
docker unpause 回复重启进程

命令如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker create nginx
427bb755b40aa50c8506862867b41f444e2fd317aac70a3336740d7f8f423e77
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" 3 seconds ago Created modest_allen
# docker start 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" 18 seconds ago Up 6 seconds 80/tcp, 443/tcp modest_allen
# docker pause 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" 29 seconds ago Up 16 seconds (Paused) 80/tcp, 443/tcp modest_allen
# docker unpause 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" 42 seconds ago Up 30 seconds 80/tcp, 443/tcp modest_allen
# docker stop 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" About a minute ago Exited (0) 3 seconds ago modest_allen
# docker restart 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" About a minute ago Up 1 seconds 80/tcp, 443/tcp modest_allen
# docker kill 427bb755b40a
427bb755b40a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bb755b40a nginx "nginx -g 'daemon off" 2 minutes ago Exited (137) 2 seconds ago modest_allen

以上操作的顺序是:create->start->pause->unpause->stop->restart->kill。注意每个操作完成之后,容器的status,主要有以下几个:

状态 含义
Created 容器已创建,尚未运行
Running(显示为 Up X seconds) 容器运行中
Paused 容器已暂停
Stopped(显示为 Exited X seconds ago ) 容器已退出运行

注意,使用stop和kill两者均能够退出容器,退出容器的区别在于,stop是正常退出,退出的返回码是0;kill是强行退出,退出的返回码是一个异常编号。

修改和提交镜像

由于提交docker hub比较慢,本文都以提交到私有的docker registry为例,即前文的reg-server。

对于需要修改的镜像,建议先标记tag,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B
# docker tag tomcat reg-server:5000/my-tomcat
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
reg-server:5000/my-tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B

tag是个很有用的命令,可以用于标记一个本地镜像(通常是即将要修改的),也可以将一个镜像归类到另一个仓库。上述命令就将tomcat镜像归类到reg-server中,并重命名为my-tomcat。注意,虽然tag重新标记了一个镜像,但是这个镜像的id并没有改变,因为镜像的id本质上是一个类似与镜像hash值的概念,只要镜像本身没有发生变化,镜像id就不会变。

删除tag与删除镜像一样,使用docker rmi,在此不再赘述。

修改镜像的方法有多种,可以挂载外部的目录到镜像的/mnt上来替换文件,也可以直接修改,本文采用直接修改的方式,比较简单。假设我们希望增加一个脚本bin/datehost.sh,打印当前的时间和hostname。可以如下操作,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker run -it reg-server:5000/my-tomcat /bin/bash
root@3fa12ef20974:/usr/local/tomcat# echo "echo \"\`date\` @ \`hostname\`\"" > bin/datehost.sh
root@eb95d2ffe224:/usr/local/tomcat# chmod +x bin/datehost.sh
root@eb95d2ffe224:/usr/local/tomcat# ls -al bin/datehost.sh
-rwxr-xr-x 1 root root 27 Dec 20 05:34 bin/datehost.sh
root@eb95d2ffe224:/usr/local/tomcat# more bin/datehost.sh
echo "`date` @ `hostname`"
root@eb95d2ffe224:/usr/local/tomcat# exit
exit
root@Ubuntu-Asus 192.168.2.104 13:35:51 /var/lib/docker
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eb95d2ffe224 reg-server:5000/my-tomcat "/bin/bash" 2 minutes ago Exited (0) 6 seconds ago insane_bhabha
# docker commit -m "add datehost.sh" eb95d2ffe224 reg-server:5000/my-tomcat
1a4f794fa3d4e507bc81c77d9daab4746f9d3eb51b06aaf6afbe55823ce4668c
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reg-server:5000/my-tomcat latest 1a4f794fa3d4 11 seconds ago 350.1 MB
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B

到这里可以发现,my-tomcat镜像已经被修改,其镜像id值已经和原先不再一样。运行一下可以发现改动已经生效,

1
2
# docker run reg-server:5000/my-tomcat bash bin/datehost.sh
Sun Dec 20 05:43:57 UTC 2015 @ 0e903602b939

修改完成之后,可以将修改后的镜像push到服务器上,如下,

1
2
3
4
5
6
7
8
9
10
11
12
# docker push reg-server:5000/my-tomcat
The push refers to a repository [reg-server:5000/my-tomcat] (len: 1)
1a4f794fa3d4: Pushed
af28fa31b54b: Pushed
7a2b734804b7: Pushed
e6c09147e1be: Pushed
1945b5ae9698: Pushed
5effacac81b9: Pushed
0a769fec47c8: Pushed
5e5f21412e19: Pushed
9ee13ca3b908: Pushed
latest: digest: sha256:3f4bc8f312bf0113c8867b8c095f7e6a4420f654e95d93559d8215c838491cb9 size: 37164

之后,可以和正常使用其他容器一样使用my-tomcat。

查找镜像

如果是在docker hub上查询,可以直接使用docker search,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# docker search redis
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redis Redis is an open source key-value store th... 1420 [OK]
torusware/speedus-redis Always updated official Redis docker image... 27 [OK]
sameersbn/redis 20 [OK]
bitnami/redis Bitnami Redis Docker Image 9 [OK]
orchardup/redis https://github.com/orchardup/docker-redis 6 [OK]
williamyeh/redis Redis image for Docker 3 [OK]
webhippie/redis Docker images for redis 2 [OK]
anapsix/redis 11MB Redis server image over AlpineLinux 2 [OK]
clue/redis-benchmark A minimal docker image to ease running the... 2 [OK]
unblibraries/redis Leverages phusion/baseimage to deploy a ba... 1 [OK]
wasabeef/redis Install latest redis-server 1 [OK]
clue/php-redis-server The php-redis-server is a pure PHP impleme... 1 [OK]
kampka/redis A Redis image build from source on top of ... 1 [OK]
greytip/redis redis 3.0.3 1 [OK]
nicescale/redis Redis services in NiceScale Platform, you ... 1 [OK]
nanobox/redis Redis service for nanobox.io 0 [OK]
yfix/redis Yfix docker redis 0 [OK]
trelllis/redis Redis Replication 0 [OK]
frodenas/redis A Docker Image for Redis 0 [OK]
appelgriebsch/redis Configurable redis container based on Alpi... 0 [OK]
rounds/10m-redis redis for hubot brain 0 [OK]
envygeeks/redis A tiny Redis image on Alpine Linux. 0 [OK]
khipu/redis customized redis 0 [OK]
fulbito/redis redis 0 [OK]
steeeveen/redis Redis server configured for migration 0 [OK]

如果是查找registry上的镜像,可以使用以下命令,

1
2
# curl -XGET http://reg-server:5000/v2/_catalog
{"repositories":["my-hello-world","my-tomcat"]}

可以看到,这里有刚才push到服务器上的my-tomcat。查看单个镜像可以用这个命令,

1
2
# curl -XGET http://reg-server:5000/v2/my-tomcat/tags/list
{"name":"my-tomcat","tags":["latest"]}

镜像和容器的导入和导出

镜像导出和导入,可以使用docker savedocker load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# docker tag mysql test-mysql
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reg-server:5000/my-tomcat latest 1a4f794fa3d4 27 minutes ago 350.1 MB
test-mysql latest a07681abeb6c 3 days ago 360.3 MB
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B
# docker save -o test-mysql.tar test-mysql
# docker rmi test-mysql
Untagged: test-mysql:latest
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reg-server:5000/my-tomcat latest 1a4f794fa3d4 29 minutes ago 350.1 MB
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B
# docker load --input test-mysql.tar
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
reg-server:5000/my-tomcat latest 1a4f794fa3d4 30 minutes ago 350.1 MB
test-mysql latest a07681abeb6c 3 days ago 360.3 MB
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B

以上命令中,docker load --input test-mysql.tar也可以用docker load < test-mysql.tar替换。

容器导出并导入镜像,可以使用docker exportdocker import

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
root@Ubuntu-Asus 192.168.2.103 13:52:34 /var/lib/docker/aufs
# docker run -d -e MYSQL_ROOT_PASSWORD=111111 mysql
f89fbfefb0ed4d23251766a4b9906175d01c767e41bf6056f6eb0d76f591774f
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f89fbfefb0ed mysql "/entrypoint.sh mysql" 8 seconds ago Up 7 seconds 3306/tcp happy_mcnulty
# docker export f89fbfefb0ed > mysql-container.tar
# cat mysql-container.tar | docker import - test-mysql-container
59d9e79d5010c22648585a3a41d5d0ee6889c0e3b92e866b0dafc99dd6aaa930
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test-mysql-container latest 59d9e79d5010 About a minute ago 358.4 MB
reg-server:5000/my-tomcat latest 1a4f794fa3d4 56 minutes ago 350.1 MB
test-mysql latest a07681abeb6c 3 days ago 360.3 MB
mysql latest a07681abeb6c 3 days ago 360.3 MB
nginx latest 5328fdfe9b8e 3 days ago 133.9 MB
tomcat latest af28fa31b54b 11 days ago 350.1 MB
busybox latest ac6a7980c6c2 11 days ago 1.113 MB
redis latest 0643f0c7d17d 2 weeks ago 109.2 MB
hello-world latest 975b84d108f1 9 weeks ago 960 B
# ls -l *mysql*
-rw-r--r-- 1 root root 365428736 1220 14:15 mysql-container.tar
-rw-r--r-- 1 root root 367499776 1220 14:06 test-mysql.tar

可以发现导入后的test-mysql的镜像id与原先不同,而且两种导出方法导出的文件大小也不一样,容器导出方式产生的文件更小一些。

其他命令

docker history可以用来查看镜像的创建历史,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# docker history test-mysql
IMAGE CREATED CREATED BY SIZE COMMENT
a07681abeb6c 3 days ago /bin/sh -c #(nop) CMD ["mysqld"] 0 B
2a044f65c047 3 days ago /bin/sh -c #(nop) EXPOSE 3306/tcp 0 B
0e44274c48b8 3 days ago /bin/sh -c #(nop) ENTRYPOINT &{["/entrypoint. 0 B
993a9b023e8d 3 days ago /bin/sh -c #(nop) COPY file:64d55f44397821c7f 3.046 kB
e8dd98df99bf 3 days ago /bin/sh -c #(nop) VOLUME [/var/lib/mysql] 0 B
ccb812e818f0 3 days ago /bin/sh -c sed -Ei 's/^(bind-address|log)/#&/ 1.771 kB
ba90d2543c21 3 days ago /bin/sh -c { echo mysql-community-server my 202 MB
040e89b06cd2 3 days ago /bin/sh -c echo "deb http://repo.mysql.com/ap 55 B
7aa0121e10fe 3 days ago /bin/sh -c #(nop) ENV MYSQL_VERSION=5.7.10-1d 0 B
a61429b086f9 2 weeks ago /bin/sh -c #(nop) ENV MYSQL_MAJOR=5.7 0 B
0d5f060b62c4 2 weeks ago /bin/sh -c apt-key adv --keyserver ha.pool.sk 20.52 kB
1b0e180fd8fa 2 weeks ago /bin/sh -c apt-get update && apt-get install 32.87 MB
e3a6552a83c2 2 weeks ago /bin/sh -c mkdir /docker-entrypoint-initdb.d 0 B
410c2fae2283 2 weeks ago /bin/sh -c groupadd -r mysql && useradd -r -g 330.4 kB
8b9a99209d5c 2 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
6d1ae97ee388 2 weeks ago /bin/sh -c #(nop) ADD file:863d6edd178364362a 125.1 MB
# docker history test-mysql-container
IMAGE CREATED CREATED BY SIZE COMMENT
59d9e79d5010 2 minutes ago 358.4 MB Imported from -

由此可以看出,采用镜像导出的方式,导出过程中丢失了每一层的信息,而是把所有层合并到一层里面,也因此,导出文件略小。

docker top可以查看一个容器正在运行的进程,

1
2
3
4
5
6
7
8
9
10
# docker run -d redis redis-server
5adefd06e5cc4434674618948e144c202b6a3560550ab42b3a44516994a99a38
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5adefd06e5cc redis "/entrypoint.sh redis" 9 seconds ago Up 8 seconds 6379/tcp sleepy_poitras
# docker top 5adefd06e5cc
UID PID PPID C STIME TTY TIME CMD
999 18602 6097 0 14:39 ? 00:00:00 redis-server *:6379

docker inspect可以查看镜像或者容器的参数,返回json格式。查看镜像的时候,与镜像本身的json文件信息一致;查看容器的时候,更多是一些运行时的参数。输出比较长,在此不列出。

docker logs可以查看容器运行时的输出日志,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5adefd06e5cc redis "/entrypoint.sh redis" 7 minutes ago Up 7 minutes 6379/tcp sleepy_poitras
root@Ubuntu-Asus 192.168.2.103 14:46:12 ~
# docker logs -f --tail 10 5adefd06e5cc
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
1:M 20 Dec 06:39:11.737 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 20 Dec 06:39:11.737 # Server started, Redis version 3.0.5
1:M 20 Dec 06:39:11.737 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 20 Dec 06:39:11.737 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
1:M 20 Dec 06:39:11.737 * The server is now ready to accept connections on port 6379

其中,-f参数表示以阻塞的方式跟踪输出日志,与linux中tail命令的-f参数含义相似;--tail n表示打印最后n行log。

docker run 命令

docker run应该是使用最多,参数也最多的docker命令了,以下介绍其中部分参数。

-d参数,表示后台运行,默认情况下docker是前台运行的,多数情况下,如果启动的是一个服务进程,我们会使用这个参数。上文已经有很多示例,在此不再举例。

-i-t参数,-t选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上,-i则让容器的标准输入保持打开。也就是说,如果要使用和用户有交互的命令,比如bash,那么需要两个选项都打开;如果只是系统自己运行,不需要与外界有输入,那么两个选项都不需要打开;如果是使用类似管道的方式进行交互,那么可以不需要-t选项,但是需要-i选项。如下,

1
2
3
4
# echo test | docker run busybox cat
# echo test | docker run -i busybox cat
test

--name参数,可以为容器命名,如下例,注意docker ps -a的最后一列,已经是我们指定的名字,

1
2
3
4
5
6
# docker run -d --name my-redis-node redis redis-server
8e0cbe8ea2877c0b68d9792804a6b64d5e13105596fae71090c3095393fcf66a
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e0cbe8ea287 redis "/entrypoint.sh redis" 5 seconds ago Up 4 seconds 6379/tcp my-redis-node

-p参数,可以将容器内部的端口映射到宿主机器,可以使用多个-p参数完成多个端口映射。之前启动服务的时候,只是用来演示docker,并没有配这一项,其实这项是非常重要的,因为如果不将端口映射到宿主机器的话,容器内的服务对容器之外的进程都是不可见的。如下例,完成端口映射之后,可以使用宿主机上的redis client访问redis容器,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# docker run -d -p 16379:6379 redis redis-server
c925ce0df258fe4b36c5295eda2a2f798bc6cde48deff73e81c0238e456c0f0c
# telnet localhost 16379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
^]
$ ./redis-cli -p 16379
127.0.0.1:16379> scan 0 count 100
1) "0"
2) (empty list or set)
127.0.0.1:16379>

-e参数,可以增加和修改环境变量,可以使用多个-e参数完成多个环境变量的增加修改。

1
2
3
4
5
6
7
8
9
10
# docker run busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f405a1d5be32
HOME=/root
# docker run -e "MYENV=test" -e "HOSTNAME=my-host" busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=my-host
MYENV=test
HOME=/root

-c-m参数,分别用来表示cpu和内存的使用限制。-c表示容器间使用cpu的优先级,默认使用100%cpu,总的cpu分成1024份,-c参数如果设置为512,那么容器只能使用50%的cpu资源。-m参数表示使用内存的上限,-m=256m表示使用内存上限是256mb。如果想限制使用cpu百分比的上限,可以使用--cpu-quota=0参数。

--rm参数,表示运行容器结束后,删除该容器。之前没有使用这个参数,在容器运行之后,docker ps -a还可以看到这个容器;使用之后,容器被删除,docker ps -a将看不到这个容器。相当与程序中的临时变量的概念。如下例,

1
2
3
4
5
6
7
8
9
10
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# docker run --rm busybox env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=a804e934d55f
HOME=/root
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

以上是docker run的主要参数,还有其他很多参数,在此不一一列举。

欢迎来到Valleylord的博客!

本博的文章尽量原创。