Docker 常用命令

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

由于 Docker 版本变化很快(笑),这篇文章的内容已经过时,可能不会再更新。建议查阅 Docker Documentation

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

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

安装

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

搜索镜像

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

使用命令搜索

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

# docker search debian

输出:

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:

# docker pull php:5.6.24-apache

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

# docker pull centos

显示本地镜像

# docker images

输出:

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

运行镜像并映射端口

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

# docker run -it -p 8080:80 e9d apache2
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

# docker run -it -p 8080:80 e9d /bin/bash
root@ac4c74c9ac8a:/var/www/html# apache2
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

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

# docker run -itd -p 8080:80 e9d /root/run.sh

参数

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

-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

列出容器

# docker ps -a
CONTAINER ID  IMAGE       COMMAND      CREATED        STATUS                    PORTS                 NAMES
ac4c74c9ac8a  e9d:latest  "/bin/bash"  7 minutes ago  Up 7 minutes              0.0.0.0:8080->80/tcp  insane_mayer
3a4b37b41ea7  e9d:latest  "apache2"    7 minutes ago  Exited (0) 7 minutes ago                        suspicious_darwin

参数

-a, --all=false       Show all containers (default shows just running)
-q, --quiet=false     Only display numeric IDs

依附到运行中的容器

ac4c 是容器号

# docker attach ac4c

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

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

在容器内增加进程

使用 docker exec 命令:

# docker exec -it 88c /bin/bash

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

容器内外复制文件

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

c9f 是容器 ID

容器外向容器内

# docker exec -i c9f /bin/sh -c 'cat > /var/static/original/img/xxx.jpg' < ./xxx.jpg
# docker exec -i 7d0 /bin/sh -c 'cat > /home/ctf/pwn1' < ./pwn1

容器内向容器外

# docker cp c9f:/opt/CTFd/CTFd/static/original/img/xxx.jpg ./

目录自动递归复制

查看端口映射

ac4c 是容器 ID

# docker port ac4c
80/tcp -> 0.0.0.0:8080

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 创建镜像

# docker build -t mylamp/test ~/Docker/mylamp_test/

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

参数

-t, --tag=            Repository name (and optionally a tag) for the image

删除镜像

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

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

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

# docker rmi 2318
# docker rmi ubuntu

删除容器

# docker rm e81

停止容器

docker stop

# docker stop e81

命令用法:

Usage:  docker stop [OPTIONS] CONTAINER [CONTAINER...]

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

使用 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 信号直接杀死容器,可以使用:

# docker kill e81

命令用法:

Usage:  docker kill [OPTIONS] CONTAINER [CONTAINER...]

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

批量操作容器

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

# docker stop $(docker ps -q)

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

# docker container prune

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

# docker rm $(docker ps -a -q)

更改容器端口

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

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

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS                    NAMES
e669c2bddb74        ctfd                "gunicorn --bind 0.0."   16 minutes ago      Up 16 minutes           0.0.0.0:8086->8000/tcp   ctfd
# docker commit e669 ctfdrunning
sha256:bae813fdc553022c9a6fdb2bb7bcddb182cb2c7ab9ef396ac9941ab3ef17a8e2
# docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
ctfdrunning           latest              bae813fdc553        4 seconds ago       507.2 MB
# docker stop e669
# docker run -itd -p 8000:8000 --name ctfd_newport ctfdrunning

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

# docker run -itd -p 8912:8000 --name ctfd_newport --volumes-from <老的 container 的 name> <ctfd 的 image 名>

查看容器详细信息

使用 docker inspect 命令:

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)

Volume

查看所有 volume

# docker volume inspect $(docker volume ls -q)

Advertisements

Comments

License

Creative Commons License

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议CC BY-NC-ND 4.0)进行许可。

This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (CC BY-NC-ND 4.0).