0%

Docker 常用命令 - Phuker’s Blog

Excerpt

这篇文章是洒家刚接触 Docker 时写的,部分操作即使在当时也不太恰当。推荐使用 Docker Compose 等容器编排工具,尽量不要直接使用 docker 命令。 由于 Docker 版本变化很快(笑),这篇文章的内容已经过时,可能不会再更新。建议查阅 Docker Documentation。 …


这篇文章是洒家刚接触 Docker 时写的,部分操作即使在当时也不太恰当。推荐使用 Docker Compose 等容器编排工具,尽量不要直接使用 docker 命令。

这篇文章最初发布于旧博客。2017 年 4 月 14 日搭建新博客时,对内容做了一些增改,作为测试文章发出来。

这篇文章针对 Ubuntu Server 16.04 和 Docker 1.12.6,主要参考《Docker 技术入门与实战》(杨保华等编著),内容都是洒家用过的命令。

Table of Contents

安装

现在 Docker 又分成了 Community Edition 和 Enterprise Edition,以前安装 docker.io 包的命令已经过时,请参考官方文档的安装方法。

搜索镜像

一般我们只需要拉取官方镜像,基于官方镜像写 Dockerfile。常用的镜像也就那几个,因此搜索功能并不常用,一般直接在 Docker Hub 网站搜索即可。

使用命令搜索

我们也可以使用 docker 命令搜索:

输出:

NAME DESCRIPTION STARS OFFICIAL AUTOMATED
debian Debian is a Linux distribution that’s comp… 1519 [OK]
neurodebian NeuroDebian provides neuroscience research… 25 [OK]
jesselang/debian-vagrant Stock Debian Images made Vagrant-friendly … 8 [OK]
armbuild/debian ARMHF port of debian 8 [OK]

常用镜像

下载镜像

指定镜像的 tag:

1
2
<span></span><code><span># </span>docker<span> </span>pull<span> </span>php:5.6.24-apache
</code>

如果不指定 tag,则视为使用默认 latest tag:

显示本地镜像

输出:

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest 4ef6a5ece191 3 days ago 120.1 MB
reinblau/lamp latest e9df29833f32 9 days ago 703.8 MB

创建并启动容器

临时运行 ubuntu:latest 镜像(退出后自动删除容器),把工作目录挂载到容器中,把宿主机 8080 端口映射到容器 80 端口

1
2
3
4
<span></span><code><span># </span>docker<span> </span>run<span> </span>-it<span> </span>--rm<span> </span>--mount<span> </span><span>"type=bind,src=</span><span>$(</span><span>pwd</span><span>)</span><span>,dst=/opt"</span><span> </span>-w<span> </span>/opt<span> </span>-p<span> </span><span>8080</span>:80<span> </span>ubuntu:latest<span> </span>bash
<span>root@0123456789ab:/opt# </span><span>pwd</span>
<span>/opt</span>
</code>

运行某 LAMP 镜像,把宿主机 8080 端口映射到容器 80 端口,e9d 是 镜像 ID 或镜像名

1
2
3
4
5
6
7
<span></span><code><span># </span>docker<span> </span>run<span> </span>-it<span> </span>-p<span> </span><span>8080</span>:80<span> </span>e9d<span> </span>apache2
<span>AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.1. Set the 'ServerName' directive globally to suppress this message</span>

<span># </span>docker<span> </span>run<span> </span>-it<span> </span>-p<span> </span><span>8080</span>:80<span> </span>e9d<span> </span>/bin/bash
<span>root@0123456789ab:/var/www/html# </span>apache2
<span>AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message</span>
</code>

在后台运行,启动后容器内自动运行 /root/run.sh

1
2
<span></span><code><span># </span>docker<span> </span>run<span> </span>-itd<span> </span>-p<span> </span><span>8080</span>:80<span> </span>e9d<span> </span>/root/run.sh
</code>

参数

加上 -i-t 可以先按 Ctrl + P,再按 Ctrl + Q unattach(退出并保持运行)。

1
2
3
4
5
6
7
<span></span><code>-d, --detach=false         Run container in background and print container ID
-i, --interactive=false Keep STDIN open even if not attached
-P, --publish-all=false Publish all exposed ports to random ports
-p, --publish=[] Publish a container's port(s) to the host
-t, --tty=false Allocate a pseudo-TTY
--name string Assign a name to the container
</code>

列出容器

1
2
3
4
5
<span></span><code><span># </span>docker<span> </span>ps<span> </span>-a
<span>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
<span>ac4c74c9ac8a e9d:latest "/bin/bash" 7 minutes ago Up 7 minutes 0.0.0.0:8080-&gt;80/tcp insane_mayer</span>
<span>3a4b37b41ea7 e9d:latest "apache2" 7 minutes ago Exited (0) 7 minutes ago suspicious_darwin</span>
</code>

参数

1
2
3
<span></span><code>-a, --all=false       Show all containers (default shows just running)
-q, --quiet=false Only display numeric IDs
</code>

依附到运行中的容器

ac4c 是容器号

操作完毕退出时,不要按 Ctrl + C,否则会停止 Docker 容器。

要先按 Ctrl + P,再按 Ctrl + Q

在容器内增加进程

使用 docker exec 命令:

1
2
<span></span><code><span># </span>docker<span> </span><span>exec</span><span> </span>-it<span> </span>88c<span> </span>/bin/bash
</code>

退出:输入 exit 命令(不必先按 Ctrl + P 再按 Ctrl + Q

容器内外复制文件

如果有这种需求,建议使用 volume。

c9f 是容器 ID

容器外向容器内

1
2
3
<span></span><code><span># </span>docker<span> </span><span>exec</span><span> </span>-i<span> </span>c9f<span> </span>/bin/sh<span> </span>-c<span> </span><span>'cat &gt; /var/static/original/img/xxx.jpg'</span><span> </span>&lt;<span> </span>./xxx.jpg
<span># </span>docker<span> </span><span>exec</span><span> </span>-i<span> </span>7d0<span> </span>/bin/sh<span> </span>-c<span> </span><span>'cat &gt; /home/ctf/pwn1'</span><span> </span>&lt;<span> </span>./pwn1
</code>

容器内向容器外

1
2
<span></span><code><span># </span>docker<span> </span>cp<span> </span>c9f:/opt/CTFd/CTFd/static/original/img/xxx.jpg<span> </span>./
</code>

目录自动递归复制

查看端口映射

ac4c 是容器 ID

1
2
3
<span></span><code><span># </span>docker<span> </span>port<span> </span>ac4c
<span>80/tcp -&gt; 0.0.0.0:8080</span>
</code>

Dockerfile

ENTRYPOINT 和 CMD 的区别

The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well.

  • CMD [“executable”,”param1”,”param2”] (exec form, this is the preferred form)
  • CMD [“param1”,”param2”] (as default parameters to ENTRYPOINT)
  • CMD command param1 param2 (shell form)

从 Dockerfile 创建镜像

1
2
<span></span><code><span># </span>docker<span> </span>build<span> </span>-t<span> </span>mylamp/test<span> </span>~/Docker/mylamp_test/
</code>

上例中,Dockerfile 文件位于 ~/Docker/mylamp_test/,镜像 tag 为 mylamp/test

参数

1
2
<span></span><code>-t, --tag=            Repository name (and optionally a tag) for the image
</code>

删除镜像

先删除所有依赖容器,再删除镜像。

后面跟上标签或 ID,跟标签会先删除标签(untag),如果没有标签指向镜像,就删除(delete)镜像。

跟 ID,删除所有相关标签(untag),再删除(delete)镜像。

1
2
3
<span></span><code><span># </span>docker<span> </span>rmi<span> </span><span>2318</span>
<span># </span>docker<span> </span>rmi<span> </span>ubuntu
</code>

删除容器

停止容器

docker stop

命令用法:

1
2
3
4
5
<span></span><code>Usage:  docker stop [OPTIONS] CONTAINER [CONTAINER...]

Options:
-t, --time int Seconds to wait for stop before killing it (default 10)
</code>

使用 docker stop 命令,Docker 首先会向容器发送一个 SIGTERM 信号。如果默认 10 秒之后没有停止,会发送 SIGKILL 信号强行停止。可以用 -t 参数修改等待时间。

Docker 1.12.6 存在的 bug:如果用一个 Shell Script 脚本作为 Docker 的 ENTRYPOINT,最后一条命令是 sleep infinity 或者 exec sleep infinity 等都会出现可以收到 SIGTERM 但是不能立即停止的问题。暂时的解决方法是 Shell Script 中最后执行 exec bash 才对 SIGTERM 有反应。

docker kill

如果想发送 SIGKILL 信号直接杀死容器,可以使用:

命令用法:

1
2
3
4
5
<span></span><code>Usage:  docker kill [OPTIONS] CONTAINER [CONTAINER...]

Options:
-s, --signal string Signal to send to the container (default "KILL")
</code>

批量操作容器

停止所有正在运行的容器:

1
2
<span></span><code><span># </span>docker<span> </span>stop<span> </span><span>$(</span>docker<span> </span>ps<span> </span>-q<span>)</span>
</code>

删除所有已经停止的容器:

删除所有已经停止的容器(旧方法,利用正在运行的容器无法删除,会报错并跳过的特性):

1
2
<span></span><code><span># </span>docker<span> </span>rm<span> </span><span>$(</span>docker<span> </span>ps<span> </span>-a<span> </span>-q<span>)</span>
</code>

更改容器端口

建议使用 Docker Compose 和 volume,不要在 container、iptables 上瞎搞。

以 CTFd 为例。老版本的 CTFd 没有使用 volume,可以直接这么搞

1
2
3
4
5
6
7
8
9
10
11
<span></span><code><span># </span>docker<span> </span>ps<span> </span>-a
<span>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
<span>e669c2bddb74 ctfd "gunicorn --bind 0.0." 16 minutes ago Up 16 minutes 0.0.0.0:8086-&gt;8000/tcp ctfd</span>
<span># </span>docker<span> </span>commit<span> </span>e669<span> </span>ctfdrunning
<span>sha256:bae813fdc553022c9a6fdb2bb7bcddb182cb2c7ab9ef396ac9941ab3ef17a8e2</span>
<span># </span>docker<span> </span>images
<span>REPOSITORY TAG IMAGE ID CREATED SIZE</span>
<span>ctfdrunning latest bae813fdc553 4 seconds ago 507.2 MB</span>
<span># </span>docker<span> </span>stop<span> </span>e669
<span># </span>docker<span> </span>run<span> </span>-itd<span> </span>-p<span> </span><span>8000</span>:8000<span> </span>--name<span> </span>ctfd_newport<span> </span>ctfdrunning
</code>

CTFd 的新版本有 volume,docker commit 不包括 volume。可以运行一个新的容器,直接加上参数

1
2
<span></span><code><span># </span>docker<span> </span>run<span> </span>-itd<span> </span>-p<span> </span><span>8912</span>:8000<span> </span>--name<span> </span>ctfd_newport<span> </span>--volumes-from<span> </span>&lt;老的<span> </span>container<span> </span>的<span> </span>name&gt;<span> </span>&lt;ctfd<span> </span>的<span> </span>image<span> </span>名&gt;
</code>

查看容器详细信息

使用 docker inspect 命令:

1
2
3
4
5
6
7
8
9
<span></span><code>Usage:  docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]

Return low-level information on a container, image or task

-f, --format Format the output using the given go template
--help Print usage
-s, --size Display total file sizes if the type is container
--type Return JSON for specified type, (e.g image, container or task)
</code>

Volume

查看所有 volume

1
2
<span></span><code><span># </span>docker<span> </span>volume<span> </span>inspect<span> </span><span>$(</span>docker<span> </span>volume<span> </span>ls<span> </span>-q<span>)</span>
</code>