跳转至

Docker 渗透基础知识

前言

平时在使用 Docker 时,经常会碰到忘记相关命令的情况,因此平时忘记一个就会记录一个,经过多年的记录,Docker 相关的笔记已经记录了不少。

最近在看代码审计的时候又提到了 Docker,正好借着这个机会好好的把原来记录的比较乱的 Docker 笔记整理一下。

如果你也面临过「在使用 Docker 时,时不时就会忘记某条命令」的情况,那么我相信本篇文章应该会对你有所帮助。

我认为 docker 容器逃逸也算是提权的一种手法, 要更好的理解容器逃逸的手法,应该知道从本质上看容器内的进程只是一个受限的普通 Linux 进程

Important

容器逃逸的过程我们完全可以将其理解为在一个受限进程中进行一些操作来获取未受限的完整权限, 或者是在原本受 Cgroup/Namespace 限制权限的进程获取更多权限, 当清晰的理解了这一点, 接下来的容器逃逸学习将会易如反掌

安装

安装 Docker

Bash
curl -fsSL https://get.docker.com/ | sh
# or use:
wget -qO- https://get.docker.com/ | sh

在命令中输入以下命令,如果输出 helloword 表示 Docker 安装成功。

Bash
docker run ubuntu echo "helloworld"

安装 Docker-Compose

Bash
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

Docker 设置国内镜像源

Bash
vi /etc/docker/daemon.json

# wirte
# note: 你需要确认该源是否可用
{
    "registry-mirrors": ["http://hub-mirror.c.163.com"]
}

systemctl restart docker.service

国内加速地址如下:

Text Only
Docker中国区官方镜像
https://registry.docker-cn.com

网易
http://hub-mirror.c.163.com

中国科技大学
https://docker.mirrors.ustc.edu.cn

阿里云容器  服务
https://cr.console.aliyun.com/
  • 重启docker服务
Bash
systemctl restart docker.service

使用

搜索镜像

Text Only
docker search centos

拉取镜像

Text Only
docker pull centos

查看镜像文件

Text Only
docker images

查看镜像层级关系

Bash
docker images tree

# 以前这个命令是:

docker images --tree

查看docker所有进程

Text Only
docker ps -a

开启容器

开启指定容器,这里的容器名为 Web

Text Only
docker start web

启动所有容器

Bash
docker start $(docker ps -aq)

进入正在运行的容器

  • docker 创建的
Bash
docker attach web
  • docker-compose 创建的

container_name 需要在 docker-compose.yml 文件中查看

Bash
docker-compose exec container_name bash

指定端口启动创建进入容器

Bash
docker run -p 9992:80 -p 8882:8888 -it ubuntu /bin/bash
docker run --name web1 -p 9991:80 -p 8881:8888 -it centos /bin/bash

导出导入镜像

export\import 导入导出

Bash
docker export web > /home/docker_web.tar
docker import /home/docker_web.tar

save\load 导入导出

Bash
docker save 9610cfc68e8d > /home/docker_web.tar
docker load < /home/docker_web.tar

export\import 与 save\load 的区别:

  • export\import 导出的镜像文件大小要小于 save\load 导出的镜像

  • export\import 是根据容器拿到的镜像,再导入时会丢失镜像所有的历史,所以无法进行回滚操作;而 save\load 的镜像,没有丢失镜像的历史,可以回滚到之前的层。

核心原因是 export 是针对容器的导出,所以只有所有层组合的最终版本;而 save 则是针对镜像的,所以可以看到每一层的信息。

修改正在运行的容器端口映射

  • 停止容器

  • 停止 docker 服务(systemctl stop docker)

  • 修改这个容器的 hostconfig.json 文件中的端口(原帖有人提到,如果 config.v2.json 里面也记录了端口,也要修改)

Bash
cd /var/lib/docker/3b6ef264a040*    # 这里是 CONTAINER ID

vi hostconfig.json

# 如果之前没有端口映射, 应该有这样的一段:
"PortBindings":{}

# 增加一个映射, 这样写:
"PortBindings":{"3306/tcp":[{"HostIp":"","HostPort":"3307"}]}

# 前一个数字是容器端口, 后一个是宿主机端口
# 而修改现有端口映射更简单, 把端口号改掉就行
  • 启动docker服务(systemctl start docker)

  • 启动容器

文件传输

Bash
# PC to container
docker cp 本地文件路径 ID全称:容器路径
# container to PC
docker cp ID全称:容器文件路径 本地路径

后台运行docker

启动全新的容器,该命令会在后台运行容器,并返回容器ID

Text Only
docker run -d

对于现有的容器

Text Only
ctrl+P+Q

卸载

停止容器

停止指定容器

Bash
docker stop web

停止所有容器

Bash
docker stop $(docker ps -aq)

删除容器和镜像

删除指定容器

Bash
docker container rm {id}
# 指定容器 ID

删除所有已退出的容器

Bash
docker rm $(docker ps -q -f status=exited)

删除所有已停止的容器

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

删除所有正在运行和已停止的容器

Bash
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

删除所有容器,没有任何标准

Bash
docker container rm $(docker container ps -aq)

Docker 资源清理

Bash
docker system df    # 查看docker磁盘使用情况
docker container prune      # 删除所有退出状态的容器
docker image prune          # 删除 dangling 或所有未被使用的镜像
docker network prune        # 删除所有未使用的网络
docker volume prune         # 删除未被使用的数据卷
docker system prune         # 删除已停止的容器、dangling 镜像、未被容器引用的 network 和构建过程中的 cache,安全起见,这个命令默认不会删除那些未被任何容器引用的数据卷,如果需要同时删除这些数据卷,你需要显式的指定 --volumns 参数
docker system prune --all --force --volumns     # 这次不仅会删除数据卷,而且连确认的过程都没有了!注意,使用 --all 参数后会删除所有未被引用的镜像而不仅仅是 dangling 镜像

删除所有镜像

Bash
docker rmi $(docker images -q)

参考:清理Docker垃圾 - 吕振江 - 博客园

卸载Docker

Bash
# centos/redhat
yum list installed | grep docker
yum -y remove docker.x86_64
# ubuntu/debian
apt remove docker

# if you use docker desktop, just delete docker desktop

卸载Docker-compose

Bash
rm /usr/local/bin/docker-compose

参考资料:

https://blog.csdn.net/a906998248/article/details/46236687

https://blog.csdn.net/wesleyflagon/article/details/78961990

Dockerfile编写

什么是 Dockerfile?

Dockerfile 是一个文本文件,包含了构建 Docker 镜像的所有指令。

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

通过定义一系列命令和参数,Dockerfile 指导 Docker 构建一个自定义的镜像。

上下文路径

Bash
docker build -t nginx:v3 .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

指令详解

Dockerfile 指令 说明
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

FROM

FROM:定制的镜像都是基于 FROM 的镜像

RUN

RUN:用于执行后面跟着的命令行命令。有以下两种格式:

shell 格式:

Docker
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

Docker
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

Docker
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

Docker
FROM centos
RUN yum -y install wget \
  && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
  && tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

Docker
COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[--chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

Docker
COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

Docker
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了--entrypoint选项,将覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

Docker
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

假设已通过 Dockerfile 构建了 nginx:test 镜像:

Docker
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 

1、不传参运行

Text Only
$ docker run nginx:test

容器内会默认运行以下命令,启动主进程。

Text Only
nginx -c /etc/nginx/nginx.conf

2、传参运行

Text Only
$ docker run nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

Text Only
nginx -c /etc/nginx/new.conf

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

Docker
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

Docker
ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用--build-arg <参数名>=<值>来覆盖。

Docker
ARG <参数名>[=<默认值>]

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。
Docker
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

EXPOSE

仅仅只是声明端口。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
Docker
EXPOSE <端口1> [<端口2>...]

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

Docker
WORKDIR <工作目录路径>

USER

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

Docker
USER <用户名>[:<用户组>]

HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

Docker
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

Docker
ONBUILD <其它指令>

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

Docker
LABEL <key>=<value> <key>=<value> <key>=<value> ...

比如我们可以添加镜像的作者:

Docker
LABEL org.opencontainers.image.authors="runoob"

Docker-compose.yml编写

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境。
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

yml 配置指令参考

version

version 用于指定 docker-compose.yml 文件所遵循的 Compose 文件版本,通常建议使用最新的版本,例如 version: '3'。版本不同,支持的配置参数也可能有所不同。

services

services 是整个配置文件的核心,定义了你所使用的各个服务(即容器)。在上面的例子中,我们定义了两个服务:web 和 db,它们分别运行 nginx 和 mysql。

build

指定为构建镜像上下文路径:

例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:

YAML
version: "3.7"
services:
  webapp:
    build: ./dir

或者,作为具有在上下文指定的路径的对象,以及可选的 Dockerfile 和 args:

YAML
version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:多层构建,可以指定构建哪一层。

cap_add/cap_drop

添加或删除容器拥有的宿主机的内核功能。

YAML
cap_add:
  - ALL # 开启全部权限

cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限

cgroup_parent

为容器指定父 cgroup 组,意味着将继承该组的资源限制。

Text Only
cgroup_parent: m-executor-abcd

command

覆盖容器启动的默认命令。

YAML
command: ["bundle", "exec", "thin", "-p", "3000"]

这个示例会覆盖 Dockerfile 中的 CMD 命令。

container_name

指定自定义容器名称,而不是生成的默认名称。

Text Only
container_name: my-web-container

depends_on

设置依赖关系。

  • docker-compose up :以依赖性顺序启动服务。在以下示例中,先启动 db 和 redis ,才会启动 web。
  • docker-compose up SERVICE :自动包含 SERVICE 的依赖项。在以下示例中,docker-compose up web 还将创建并启动 db 和 redis。
  • docker-compose stop :按依赖关系顺序停止服务。在以下示例中,web 在 db 和 redis 之前停止。
Text Only
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

注意:depends_on 只控制启动顺序,并不确保依赖服务完全准备好(例如数据库完全启动并能够接受连接)。为确保这一点,可以在应用中实现健康检查机制。

deploy

指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用。

YAML
version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

可以选参数:

endpoint_mode:访问集群服务的方式。

YAML
endpoint_mode: vip 
# Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
# DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。

labels:在服务上设置标签。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下的 labels。

mode:指定服务提供的模式。

  • replicated:复制服务,复制指定服务到集群的机器上。

  • global:全局服务,服务将部署至集群的每个节点。

  • 图解:下图中黄色的方块是 replicated 模式的运行情况,灰色方块是 global 模式的运行情况。

img

replicas:mode 为 replicated 时,需要使用此参数配置具体运行的节点数量。

resources:配置服务器资源使用的限制,例如上例子,配置 redis 集群运行需要的 cpu 的百分比 和 内存的占用。避免占用资源过高出现异常。

restart_policy:配置如何在退出容器时重新启动容器。

  • condition:可选 none,on-failure 或者 any(默认值:any)。
  • delay:设置多久之后重启(默认值:0)。
  • max_attempts:尝试重新启动容器的次数,超出次数,则不再尝试(默认值:一直重试)。
  • window:设置容器重启超时时间(默认值:0)。

rollback_config:配置在更新失败的情况下应如何回滚服务。

  • parallelism:一次要回滚的容器数。如果设置为0,则所有容器将同时回滚。
  • delay:每个容器组回滚之间等待的时间(默认为0s)。
  • failure_action:如果回滚失败,该怎么办。其中一个 continue 或者 pause(默认pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)。
  • max_failure_ratio:在回滚期间可以容忍的故障率(默认为0)。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认 stop-first )。

update_config:配置应如何更新服务,对于配置滚动更新很有用。

  • parallelism:一次更新的容器数。
  • delay:在更新一组容器之间等待的时间。
  • failure_action:如果更新失败,该怎么办。其中一个 continue,rollback 或者pause (默认:pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)。
  • max_failure_ratio:在更新过程中可以容忍的故障率。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认stop-first)。

注:仅支持 V3.4 及更高版本。

devices

指定设备映射列表。

Text Only
devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

dns

自定义 DNS 服务器,可以是单个值或列表的多个值。

Text Only
dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 9.9.9.9

自定义 DNS 搜索域。可以是单个值或列表。

Text Only
dns_search: example.com

dns_search:
  - dc1.example.com
  - dc2.example.com

entrypoint

覆盖容器默认的 entrypoint。

Text Only
entrypoint: /code/entrypoint.sh

也可以是以下格式:

YAML
entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

env_file

从文件添加环境变量。可以是单个值或列表的多个值。

Text Only
env_file: .env

也可以是列表格式:

Text Only
env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

environment

添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。

Text Only
environment:
  RACK_ENV: development
  SHOW: 'true'

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

仅可以指定内部端口为参数:

Text Only
expose:
 - "3000"
 - "8000"

extra_hosts

添加主机名映射。类似docker client --add-host。

YAML
extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:

Text Only
162.242.195.82  somehost
50.31.209.229   otherhost

healthcheck

用于检测 docker 服务是否健康运行。

YAML
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

image

指定容器运行的镜像。以下格式都可以:

Text Only
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

logging

服务的日志记录配置。

driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项

YAML
driver: "json-file"
driver: "syslog"
driver: "none"

仅在 json-file 驱动程序下,可以使用以下参数,限制日志数量和大小。

YAML
logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

当达到文件限制上限,会自动删除旧文件。

syslog 驱动程序下,可以使用 syslog-address 指定日志接收地址。

YAML
logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

network_mode

设置网络模式。

YAML
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

配置容器连接的网络,引用顶级 networks 下的条目 。

YAML
services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases :同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。

restart

  • no:是默认的重启策略,在任何情况下都不会重启容器。
  • always:容器总是重新启动。
  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
Text Only
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

注:swarm 集群模式,请改用 restart_policy。

secrets

存储敏感数据,例如密码:

YAML
version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt

security_opt

修改容器默认的 schema 标签。

YAML
security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签

stop_grace_period

指定在容器无法处理 SIGTERM (或者任何 stop_signal 的信号),等待多久后发送 SIGKILL 信号关闭容器。

Text Only
stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 

默认的等待时间是 10 秒。

stop_signal

设置停止容器的替代信号。默认情况下使用 SIGTERM 。

以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器。

Text Only
stop_signal: SIGUSR1

sysctls

设置容器中的内核参数,可以使用数组或字典格式。

YAML
sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

tmpfs

在容器内安装一个临时文件系统。可以是单个值或列表的多个值。

Text Only
tmpfs: /run

tmpfs:
  - /run
  - /tmp

ulimits

覆盖容器默认的 ulimit。

Text Only
ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes

将主机的数据卷或者文件挂载到容器里。

YAML
version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"

example

YAML
# wordpress + mysql
version: '3'
services:
  wordpress:
    image: wordpress
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
    depends_on:
      - db
    volumes:
      - wordpress_data:/var/www/html

  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: examplepass
      MYSQL_DATABASE: wordpress
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
    volumes:
      - db_data:/var/lib/mysql

volumes:
  wordpress_data:
  db_data:
YAML
# React + Nginx + Node.js 的前后端应用
version: '3'
services:
  frontend:
    build:
      context: ./frontend
    ports:
      - "3000:3000"
    volumes:
      - ./frontend/src:/app/src
    depends_on:
      - backend
    networks:
      - app-network

  backend:
    build:
      context: ./backend
    ports:
      - "5000:5000"
    networks:
      - app-network
    environment:
      DATABASE_URL: mongodb://mongo:27017/mydb

  mongo:
    image: mongo
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db
    networks:
      - app-network

volumes:
  mongo-data:

networks:
  app-network: