1 Docker tutorial

1 Docker 简介

1.1 什么是 Docker

Docker 是一种虚拟化技术。

与传统的虚拟机技术的对比:

这里写图片描述


1.2 为什么用 Docker

Docker 的优势

  • 更高效的利用系统资源
  • 更快的启动时间
  • 一致的运行环境
  • 持续交付和部署
  • 更轻松的迁移
  • 更轻松的维护和扩展

这里写图片描述


2 基本概念

2.1 镜像(Image)

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像不包含任何动态数据,其内容在构建之后也不会被改变。

分层存储

镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像在构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。

分层存储的特征还使得镜像的复用、定制变得更为容易,甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。


2.2 容器(Container)

Image 与 Container 的关系,就像 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,其运行在一个隔离的环境里,使用起来好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。

由于镜像是分层存储的,那么容器也是如此。每一个容器运行时,是以镜像为基础层,在其上构建一个当前容器的存储层(容器存储层)。容器存储层的生命周期和容器一样,容器消亡是,容器存储层也随之消亡,因此任何保存于容器存储层的信息都会随容器删除而消失。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。


2.3 仓库(Registry)

Docker Registry 就是一个集中存储、分发镜像的服务。

一个 Docker Registry 中可以包含多个仓库,每个仓库可以包含多个标签,每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。


3 安装 Docker

详见官网 安装指南


4 使用镜像

4.1 获取镜像

4.1.1 docker pull

命令格式:

docker pull [选项] [Docker Registry地址]<仓库名>:<标签>

  • Docker Registry地址:地址的格式一般是 <域名/IP>[:端口号],默认地址是 Docker Hub。
  • 仓库名: 仓库名是两段式名称,即 <用户名>/<软件名>,对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

Usage

docker pull ubuntu:14.04

4.1.2 运行容器

docker run -it –rm ubuntu:14.04 bash

参数讲解:

  • -it: 这是两个参数,-i 指的是交互式操作,一个是 -t 指终端。我们打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • --rm: 这个参数是说容器退出后随之将其删除。
  • ubuntu:14.04: 这是指用 ubuntu:14.04 镜像为基础来启动容器。
  • bash: 放在镜像后面的是命令,这里我们希望有个交互式 Shell,因此用的是 bash

最后我们可以通过 exit 来退出容器。


4.2 列出镜像

docker images: 列出所有已经下载下来的镜像。

列表中包含了仓库名、标签、镜像 ID、创建时间以及所占用的空间。其中镜像 ID 是镜像的唯一标识,一个镜像可以对应多个标签。

镜像体积

关于镜像体积有两点需要说明:

  1. docker images 显示的是镜像下载到本地后,展开后的各层所占空间的总和,与 Docker Hub 上看到的大小不同(Docker Hub 中显示的体积是压缩后的体积)。
  2. docker images 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。这是因为 Docker 镜像是多层存储结构,并且可继承、复用,因此不同的镜像可能拥有相同的基础镜像,从而拥有相同的层;Docker 使用 Union FS,相同的层只需保存一份即可。

虚悬镜像(dangling image)

没有仓库名,也没有标签的镜像称之为虚悬镜像。
产生的原因是由于新旧镜像同名,旧镜像名称被取消。

虚悬镜像没有存在的意义,可以随意删除:

docker rmi $(docker images -q -f dangling=true)

中间层镜像

列出中间层镜像

docker images -a

这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其他镜像所依赖的镜像。
中间层镜像不应该被删除,否则会导致上层镜像因为依赖丢失而出错。

列出部分镜像

根据仓库名列出镜像

docker images ubuntu

根据指定仓库名和标签列出镜像

docker images ubuntu:v1

以特定的格式列出镜像

docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"


4.3 利用 commit 理解镜像构成

首先,启动一个容器

docker run --name webserver -d -p 80:80 nginx

其次,进入容器修改其内容

docker exec -it webserver bash
root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit

此时,我们已经修改了容器的存储层,重启容器所做修改将会丢失。
docker commit 命令可以在原有镜像的基础上,再叠加容器的存储层,并构成新的镜像

最后,docker commit 制作新的镜像

docker commit \
--author "Tao Wang <twang2218@gmail.com>" \
--message "修改了默认网页" \
webserver \
nginx:v2

新的镜像制作好后,我们可以运行这个镜像

docker run --name web2 -d -p 81:80 nginx:v2

docker commit 的语法格式为:

docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

综述:

Note: 慎用 docker commit,原因有以下两点
1. docker commit 对镜像的操作为黑箱操作,只有镜像的制作者才知道如何制作镜像以及执行过哪些命令。
2. docker commit 对镜像的操作都是在容器的当前层操作,每一层 docker commit 的操作都会让镜像变得更加臃肿。


4.4 使用 Dockerfile 定制镜像

Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令就是在描述该层应当如何构建。

使用 Dockerfile 脚本构建镜像,解决了镜像无法重复构建、构建透明性以及构建体积越来越臃肿的问题。

构建实例:

在一个空的目录中,建立一个文本文件,并命名为 Dockerfile

$ mkdir mynginx
$ cd mynginx
$ touch Dockerfile

其内容为:

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基础镜像

所谓定制镜像,那一定是以一个镜像为基础的,在其上进行定制。FROM 就是指定基础镜像。

RUN 执行命令

RUN 指令是用来执行命令行命令的。其格式有两种:

  • shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式。

每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。

因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该被清理掉。

FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/r
edis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-component
s=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps

构建镜像

使用 docker build 命令来构建镜像,其格式为

docker build [选项] <上下文路径/URL/->

基于上例,在 Dockerfile 文件所在目录执行

docker build -t nginx:v3 .

镜像构建上下文

Docker 是一种 C/S 设计的软件,分为 Docker 引擎和 Docker 客户端,docker 客户端工具通过 Docker Remote API 与 Docker 引擎交互,从而完成各种功能。

使用 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建。
当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包,展开就会获得构建镜像所需的一切文件。

一般来说,应该会将 Dockfile 置于一个空目录下,或者项目根目录下。如果该项目没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .dockerignore 文件,剔除不需要构建的文件。

那么为什么会有人误以为 . 是指定 Dockerfile 所在目录呢?这是因为在默认情况下,如果不额外指定 Dickerfile 的话,会将上下文目录下的名为 Dockerfile 的文件作为 Dockerfile。
这只是默认行为,实际上 Dockerfile 的文件名并不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,比如可以用 -f ../Dockfile.php 参数指定为某个文件为 Dockerfile

其它 docker build 的用法

直接用 Git repo 进行构建

docker build https://github.com/twang2218/gitlab-ce-zh.git\#:8.14

用给定的 tar 压缩包构建

docker build http://server/context.tar.gz

从标准输入中读取 Dockerfile 进行构建

docker build - < Dockerfile

如果标准输入传入的是文本文件,则将其视为 Dockerfile ,并开始构建。这种
形式由于直接从标准输入中读取 Dockerfile 的内容,它没有上下文,因此不可以像
其他方法那样可以将本地文件 COPY 进镜像之类的事情。

从标准输入中读取上下文压缩包进行构建

docker build - < context.tar.gz

如果发现标准输入的文件格式是 gzip 、 bzip2 以及 xz 的话,将会使其为上
下文压缩包,直接将其展开,将里面视为上下文,并开始构建。


4.5 Dockerfile 指令详解

COPY 复制文件

格式:

  • COPY <源路径>... <目标路径>
  • COPY ["<源路径1>", ... "<目标路径>"]

COPY 指令将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的 <目标路径> 位置,比如:

COPY package.json /usr/src/app/

<源路径> 可以是多个,甚至可以是通配符
<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以使用 WORKDIR 指令来指定),目标目录不存在会先创建。

此外,还需要注意一点,使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。

ADD 更高级的复制

ADD 指令和 COPY 的格式和性质基本一致。

我们可以遵循这样的原则:所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合下使用 ADD

CMD 容器启动命令

CMD 指令的格式和 RUN 相似,也就是两种格式:

  • shell 格式:CMD <命令>
  • exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
  • 参数列表格式: CMD [“参数1”, “参数2”…] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

CMD 指令就是用于指定默认的容器主进程的启动命令的。

在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一般使用双引号 ",而不是单引号。

如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:

CMD echo $HOME

在实际执行中会变为:

CMD ["sh", "-c", "echo $HOME"]

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

ENTRYPOINT 入口点

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。

当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

使用 ENTRYPOINT 的好处如下:

  • 让镜像变成命令一样使用
  • 应用运行前的准备工作

ENV 设置环境变量

格式有两种:

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

这个命令就是用于设置环境变量,以便后面的命令可以使用这些环境变量。

ARG 构建参数

格式:ARG <参数名>[=<默认值>]

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

VOLUME 定义匿名卷

格式为:

  • VOLUME ["<路径1>", "<路径2>"...]
  • VOLUME <路径>

之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存在卷(VOLUME)中。

定义匿名卷:VOLUME /data
定义命名卷:VOLUME /data:mydata

EXPOSE 声明端口

格式为:EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口服务。

要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。-p 是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。

WORKDIR 指定工作目录

格式为:WORKDIR <工作目录路径>

使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如果目录不存在,WORKDIR 会帮你创建。

USER 指定当前用户

格式为:USER <用户名>

USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及ENTRYPOINT 这类命令的身份。
USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

HEALTHCHECK 健康检查

格式:

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

HEALTHCHECK 指令是告诉 Docker 应该如果进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。在此之前,Docker 引擎只能通过容器内主进程是否退出来判断容器是否状态异常,但是如果主进程进入死锁或者死循环,应用进程不退出,但容器已经不能提供服务了,这种情况下 Docker 引擎不会重新调度。

当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为
starting ,在 HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定
次数失败,则会变为 unhealthy

HEALTHCHECK 支持下列选项:

  • –interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
  • –timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次
    健康检查就被视为失败,默认 30 秒;
  • –retries=<次数> :当连续失败指定次数后,则将容器状态视为
    unhealthy ,默认 3 次。

和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,
只有最后一个生效。

HEALTHCHECK [选项] CMD 后面的命令,格式和 ENTRYPOINT 一样,分为
shell 格式,和 exec 格式。命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留,不要使用这个值。

例如:检查 Web 服务是否正常

FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib
/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1

4.6 其它制作镜像的方式

从 rootfs 压缩包导入

格式:

docker import [选项] <文件>|[URL]|- [<仓库名>[:<标签>]]

示例:

docker import \
http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz \
openvz/ubuntu:14.04

docker save 和 docker load

Docker 提供了 docker loaddocker save 命令,用以将镜像保存为一个 tar 文件,然后传输到另一个位置上,再加载进来。

保存镜像:

docker save nginx | gzip > nginx-v1.tar.gz

加载镜像:

docker load -i nginx-v1.tar.gz

不过,这些现已经不推荐,镜像的迁移应该直接使用 Docker Registry。


4.7 删除本地镜像

删除本地镜像可以用 docker rmi 命令,其格式为:

docker rmi [选项] <镜像1> [<镜像2> ...]

注意 docker rm 是删除容器,不要混淆。

用镜像ID删除镜像

docker rmi 0584b3d2cf6d

用镜像名删除镜像

镜像名即<仓库名>:<标签>

docker rmi nginx:v1

使用镜像摘要删除镜像

docker images --digests:显示镜像摘要

docker rmi node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

另外,镜像的删除行为分为两类,一类是 Untagged,一类是 Deleted


5 操作容器

简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。

5.1 启动容器

启动容器有两种方式

  • 基于镜像新建一个容器并启动
  • 在终止状态(stopped)的容器重新启动

因为 Docker 的容器实在是太轻量了,很多时候用户都是随时删除和新建容器。

新建并启动

所需的命令主要为 docker run

docker run ubuntu:14.04 /bin/echo 'Hello World'

启动容器并打开输入端

docker run -it ubuntu /bin/bash

启动已终止容器

可以使用 docker start 命令,来启动已终止的容器。

docker start webserver


5.2 守护态运行

更多的时候,需要让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下,此时可以通过添加 -d 参数来实现。

sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

注: 容器是否会长久运行,是和 docker run 指定的命令有关,和 -d 参数无关。

可以使用 docker ps 命令查看容器信息。

docker ps

要获取容器的输出信息,可以通过 docker logs 命令。

docker logs [Container ID or NAMES]


5.3 终止容器

可以使用 docker stop 来终止一个运行中的容器,此外,当 Docker 容器中指定的应用终结时,容器也会自动终止。(例如只启动了一个终端容器)

终止状态的容器可以用 docker ps -a 命令查看到,可以使用 docker start 重新启动。
使用 docker restart 可以重启一个运行中的容器。


5.4 进入容器

在某些时候需要进入容器进行操作,可以使用 docker attach 命令或 nsenter 等工具。

exec 命令

docker exec -it d48b21a7e439 /bin/sh

nsenter 命令

nsenter 启动一个新的 shell 进程(默认是 /bin/bash),同时会把这个新进程切换到和目标进程相同的命名空间,这样就相当与进入了容器的内部。

源码安装

$ cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linu
x/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
$ ./configure --without-ncurses
$ make nsenter && sudo cp nsenter /usr/local/bin

使用:
为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取。

PID=$(docker inspect --format "{{ .State.Pid }}" <container>)

通过这个 PID,就可以连接到这个容器:

nsenter --target $PID --mount --uts --ipc --net --pid

如果无法通过以上命令连接到这个容器,有可能是因为宿主的默认shell在容器中并不存在,比如zsh,可以使用如下命令显式地使用bash。

$ nsenter --target $pid --mount --uts --ipc --net --pid -- /usr/bin/env --ignore-environment HOME=/root /bin/bash --login

5.5 导出和导入

导出容器

使用 docker export 命令可以导出本地某个容器

docker export 76954831da5s5 > ubuntu.tar

导入容器快照

cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0

Note:用户既可以使用 docker load 来导入镜像存储文件到本地镜像库,也可以使用 docker import 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。


5.6 删除容器

可以使用 docker rm 来删除一个处于终止状态的容器

docker rm docker_nginx_webserver

如果要删除一个运行中的容器,可以添加 -f 参数。

清理所有处于终止状态的容器

docker rm 命令默认并不会删除运行中的容器。

docker rm $(docker ps -a -q)


6 访问仓库

6.1 Docker Hub

目前 Docker 官方维护了一个公共的仓库 Docker Hub,其中大部分需求都可通过在 Docker Hub 中直接下载镜像来实现。

搜索镜像

docker search centos

下载镜像

docker pull centos

上传镜像

docker push centos:v1


6.2 私有仓库


7 数据管理

在容器中管理数据主要有两种方式:

  • 数据卷(Data volumes)
  • 数据卷容器(Data volume containers)

7.1 数据卷

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

  • 数据卷可以在容器之间共享和使用
  • 对数据卷的修改立马会生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除

创建一个数据卷

在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。

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

删除数据卷

数据卷是独立与容器存在的,并不会随着容器的删除而消失,在删除容器的时候使用 docker rm -v 这个命令在删除容器时同时移除数据卷。

挂载一个主机目录作为数据卷

使用 -v 标记可以指定挂载一个本地主机目录到容器中

docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

Docker 挂载数据卷的默认权限是读写的,用户也可以通过 :ro 指定为只读。

docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

Note: Dockerfile 中不支持这种用法,因为 Dockerfile 是为了移植和分享用的,然而。不同操作系统的路径格式不一样,所以目前还不能支持。

查看数据卷的具体信息

在主机里使用以下命令可以查看指定容器的信息

docker inspect web

7.2 数据卷容器

如果你有一些持续更新的数据需要在容器之间共享,最好的方式就是创建数据卷容器。

顾名思义,数据卷容器其实就是一个正常的容器,专门用来提供数据卷供其他容器挂载的。

首先,创建一个名为 dbdata 的数据卷容器

docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

然后,在其他容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷

docker run -d --volumes-from dbdata --name db1 training/postgres
docker run -d --volumes-from dbdata --name db2 training/postgres

也可以从其他已经挂载了数据卷的容器来级联挂载数据卷

docker run -d --name db3 --volumes-from db1 training/postgres

7.3 利用数据卷容器来备份、恢复、迁移数据卷

备份

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

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

容器启动后,使用 tar 命令来将 dbdata 卷备份为容器中 /backup/backup.tar 文件,也就是主机当前目录下名为 backup.tar 的文件。

恢复

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

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

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

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

为了查看/验证恢复的数据,可以再启动一个容器挂在挂载同样的容器卷来查看

docker run --volumes-from dbdata2 busybox /bin/ls /dbdata

8 使用网络

8.1 外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P-p 参数来指定端口映射。

  1. 当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。

  2. 当使用 -p 标记时,可以指定要映射的端口,并且在一个指定端口上只可以绑定一个容器。

映射所有接口地址

使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行

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

此时默认会绑定本地所有接口上的所有地址

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

可以使用 ip:hostPort:containerPort 格式,指定映射一个特定的地址,比如 localhost 地址 127.0.0.1

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

映射指定地址的任意端口

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

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

查看映射端口配置

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

docker port nostalgic_morse 5000

Note:
- 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置)
- -p 标记可以多次使用来绑定多个端口

docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py

8.2 容器互联

容器的连接系统是除了端口映射外,另一种跟容器中应用交互的方式。

该系统会在源和接收容器之间建立一个隧道,接收容器可以看到源容器指定的信息。

自定义容器命名

使用 --name 标记可以为容器自定义命名

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

使用 docker ps -l 来验证命名

容器互联

使用 --link 参数可以让容器之间安全的进行交互。

首先,先创建一个新的数据库容器

docker run -d --name db training/postgres

然后,创建一个新的 web 容器,并将它连接到 db 容器

docker run -d -P --name web --link db:db training/webapp python app.py

此时,db 容器和 web 容器建立互联关系

--link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。

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

  • 环境变量
  • 更新 /etc/hosts 文件

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

$ 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 文件

$ 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

这里有 2 个 hosts,第一个是 web 容器,web 容器用 id 作为他的主机名,第二个是 db 容器的 ip 和主机名。

用户可以链接多个父容器到子容器,比如可以链接多个 web 到 db 容器上。

Docker 命令大全

Docker 命令大全

12 Docker 之 Compose

12.1 简介

compose 的定位是”定义和运行多个 Docker 容器的应用”。它允许用户通过一个单独的 docker-compose.yml 模板文件来定义一组相关联的应用容器为一个项目。

Compose 中有两个重要的概念:

  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
  • 项目(project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义

12.2 安装和卸载

详见官方文档

12.3 命令对象与格式

对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或容器。如果没有特别说明,命令对象将是项目,这意味着项目中所有的服务都会收到命令影响。

compose 命令的基本格式为

docker-compose [-f=<arg>...] [options] [command] [args...]

命令选项:

  • -f:指定使用的 Compose 模板文件,默认为 docker-compose.yml
  • -p:指定项目名称,默认将使用所在目录名作为项目名
  • -v:打印版本并退出
  • --x-networking:使用 Docker 的可拔插网络后端特性
  • --x-network-driver:指定网络后端驱动,默认为 bridge
  • --verbose 输出更多调试信息

命令说明:

  • builddocker-compose build [options] [service...],构建或重构项目中的服务容器。
  • help:获得命令帮助
  • killdocker-compose kill [options] [service...],停止服务容器
  • logsdocker-compose logs [options] [service...],查看服务容器输出
  • pausedocker-compose pause [service],暂停一个服务容器
  • portdocker-compose port [options] service private_port,打印某个容器所映射的公共端口
  • psdocker-compose ps [options] [service],列出项目中目前的所有容器
  • pulldocker-compose pull [options] [service...],拉取服务依赖的镜像
  • restartdocker-compose restart [options] [service...],重启项目中的服务
  • rmdocker-compose rm [options] [service...],删除所有(停止状态的)服务容器
  • rundocker-compose run [options] [-p PORT...] service [command] [args...],在指定服务上执行一个命令。
  • scale:设置同一个服务运行的容器个数
  • start:启动一个已存在的服务容器
  • stop:停止一个已经运行的容器,但不删除它
  • updocker-compose up [options] [service],它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作,可以说,大部分的时候都可以直接通过该命令来启动一个项目。

12.4 compose 模版文件

version: "2"
services:
    webapp:
        image: examples/web
        ports:
            - "80:80"
        volumes:
            - "/data"

所有的服务需放在 services 根下面,另外,每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。

下面分别介绍各个指令的用法:

Service 配置参考

注意:有多个版本的Compose文件格式 - 版本1(旧版格式,不支持卷或网络)和版本2以及2.1(最新的)。 有关更多信息,请参阅版[Versioning]部分。

此部分包含服务定义支持的所有配置选项的列表。

build

在构建时应用的配置选项。

build可以指定为包含构建上下文路径,也可以根据上下文选择 dockerfile 和 args 指定的路径对象。

build: ./dir

build:
  context: ./dir
  dockerfile: Dockerfile-alternate
  args:
    buildno: 1

如果指定image字段来build,则Compose使用image中指定的webapptag(可选)命名构建的image

build: ./dir
image: webapp:tag

这里从./dir构建了一个镜像名为webapp,并打上标记为tag的镜像。

注意:在版本1文件格式中,build有两种不同的方法:

  1. 只允许字符串形式(build:.) - 而不是对象形式。
  2. 不允许与image一起build。 尝试这样做会导致错误。
context

版本2及以上使用,版本1只使用build。

它的值可以是Dockerfile的路径,或者是指向git仓库的url。

当提供的值是相对路径时,它被解释Compose文件位置的相对路径。 目录里的信息会被当做构建内容 发送到Docker守护进程。

Compose将使用生成的名字buildtag它,然后使用该image

build:
  context: ./dir
dockerfile

备用Dockerfile。

撰写将使用一个备用文件来构建。 还必须指定构建路径。

build:
  context: .
  dockerfile: Dockerfile-alternate

注意:在版本1文件格式中,dockerfile有两种不同的方法:

  1. 它与build同级出现,而不是子选项:
  build: .
  dockerfile: Dockerfile-alternate
  1. 不允许与image一起使用dockerfile。 尝试这样做会导致错误。
args

支持版本2及以上

添加构建参数,它们是只有在构建过程中才可访问的环境变量。

首先,在Dockerfile中指定参数:

ARG buildno
ARG password

RUN echo "Build number: $buildno"
RUN script-requiring-password.sh "$password"

然后,指定build字段下的参数args。您可以mapping或list:

build:
  context: .
  args:
    buildno: 1
    password: secret

build:
  context: .
  args:
    - buildno=1
    - password=secret

指定build参数时,可以忽略该值,在这种情况下,构建时其值为运行Compose的环境中的值。

args:
  - buildno
  - password

注意:YAML布尔值(true,false,yes,no,on,off)必须用引号引起来,以便解析器将其解释为字符串。

cap_add, cap_drop

添加或删除容器功能。 有关完整列表,请参阅man 7功能。

cap_add:
  - ALL

cap_drop:
  - NET_ADMIN
  - SYS_ADMIN
command

覆盖默认命令

command: bundle exec thin -p 3000

该命令也可以是一个list,在方式类似于dockerfile:

command: [bundle, exec, thin, -p, 3000]
cgroup_parent

为容器指定可选的父cgroup。

cgroup_parent: m-executor-abcd
container_name

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

container_name: my-web-container

由于Docker容器名称必须是唯一的,因此如果您指定了自定义名称,则无法将服务扩展到1个容器之外。 尝试这样做会导致错误。

devices

设备映射列表。 使用与--device docker client create选项相同的格式。

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"
depends_on

Express之间的依赖关系,有两个效果:

  • docker-compose up 将按照依赖顺序启动服务。 在下面的示例中,db和redis将在web之前启动。
  • docker-compose up SERVICE 将自动包含SERVICE的依赖关系。 在以下示例中,docker-compose up web也将创建并启动db和redis。

列子:

version: '2'
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

注意:在启动web之前,depends_on不会等待db和redis“就绪”,直到它们被启动。 如果您需要等待服务准备就绪,请参阅控制启动顺序了解有关此问题的更多信息以及解决问题的策略。

dns

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

dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9
dns_search

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

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

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

tmpfs: /run
tmpfs:
  - /run
  - /tmp
entrypoint

覆盖默认的entrypoint

entrypoint: /code/entrypoint.sh

entrypoint也可以是一个列表,存在方式类似于dockerfile:

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

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

如果已使用docker-compose -f FILE指定了一个Compose文件,则env_file中的路径相对于该文件所在的目录。

在环境中指定的环境变量会覆盖这些值。

env_file: .env

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

Compose期望env文件中的每一行都处于VAR = VAL格式。 以#开头的行(即注释)将被忽略,空行也是如此。

# Set Rails/Rack environment
RACK_ENV=development

注意:如果您的service指定了build选项,则在build过程中将不会自动显示环境文件中定义的变量。 使用build的args子选项来定义构建时环境变量。

environment

添加环境变量。您可以使用数组或字典。 任意布尔值:true,false,yes no,需要用引号括起来,以确保它们不会被YML解析器转换为True或False。

只有一个键的环境变量被解析为它在Compose正在运行的机器上的值,这对于secret或host-specific values是有帮助的。

environment:
  RACK_ENV: development
  SHOW: 'true'
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SHOW=true
  - SESSION_SECRET

注意:如果您的服务指定了build选项,则在build期间将不会自动显示在环境中定义的变量。 使用build的args子选项来定义构建时环境变量。

expose

公开端口,而不将其发布到主机 - 它们只能访问链接服务。只能指定内部端口。

expose:
 - "3000"
 - "8000"
extends

在当前文件或另一个文件中扩展另一个服务,可选地覆盖配置。

您可以将extends与其他配置字段一起使用。 extends值必须是使用必需的server和可选file字段定义的字典。

extends:
  file: common.yml
  service: webapp

server正在扩展的服务的名称,例如web或数据库。 该文件是定义该服务的Compose配置文件的位置。

如果省略file Compose在当前文件中查找服务配置。 file值可以是绝对路径或相对路径。 如果指定相对路径,则Compose将其视为相对于当前文件的位置。

您可以扩展本身扩展其他服务。 您可以无限期地延长。 Compose不支持循环引用,如果遇到一个,docker-compose会返回一个错误。

有关扩展的更多信息,请参阅扩展文档

链接到在docker-compose.yml外部启动的容器,甚至在Compose之外,特别是对于提供共享或公共服务的容器。 external_links在指定容器名称和链接别名(CONTAINER:ALIAS)时遵循类似于links的语义。

external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql

注意:如果您使用的是版本2文件格式,则外部创建的容器必须连接到至少一个与链接到它们的服务相同的网络。

extra_hosts

添加主机名映射。使用与docker client --add-host参数相同的值。

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

具有ip地址和主机名的条目将在此服务的容器中的/etc/hosts中创建,例如:

162.242.195.82  somehost
50.31.209.229   otherhost
group_add

指定容器中的用户将成为其成员的其他组(按名称或号码)。 组必须存在于要添加的容器和主机系统中。 这是有用的一个例子是当多个容器(作为不同的用户运行)需要在主机系统上读取或写入相同的文件。 该文件可以由所有容器共享的组拥有,并在group_add中指定。 有关更多详细信息,请参阅Docker文档

version: '2'
services:
    image: alpine
    group_add:
      - mail

在创建的容器中运行id将显示用户属于mail组,如果未使用group_add,则不会是这种情况。

image

指定要从中启动容器的映像。可以是存储库/标记或部分图像ID。

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd

如果image不存在,Compose会尝试拉取它,除非你也指定了build,在这种情况下,它使用指定的选项构建它,并用指定的标签标记它。

注意:在版本1文件格式中,不允许与image一起使用build。 尝试这样做会导致错误。

isolation

Added in version 2.1 file format.指定容器的隔离技术。在Linux上,唯一支持的值为default。 在Windows上,可接受的值为defaultprocesshyperv。 有关详细信息,请参阅Docker Engine文档

labels

使用Docker labels向容器添加元数据。 您可以使用list或mapping。

建议您使用reverse-DNS符号来防止您的标签与其他软件使用的标签冲突。

labels:
  com.example.description: "Accounting webapp"
  com.example.department: "Finance"
  com.example.label-with-empty-value: ""

labels:
  - "com.example.description=Accounting webapp"
  - "com.example.department=Finance"
  - "com.example.label-with-empty-value"

链接到另一个服务中的容器。请指定服务名称和链接别名(SERVICE:ALIAS),或仅指定服务名称。

web:
  links:
   - db
   - db:database
   - redis

如果未指定别名,则可以在与别名相同的主机名或服务名称处访问链接服务的容器。

链接也以与depends_on相同的方式表示服务之间的依赖关系,因此它们确定服务启动的顺序。

注意:如果您定义链接和networks,则具有它们之间的链接的服务必须共享至少一个公共网络以便进行

logging

Version 2 file format and up. In version 1, use log_driver and log_opt.

记录服务的配置。

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

driver名称指定了服务容器的日志驱动程序,,如docker运行的--log-driver选项(documented here)。

默认值为json-file。

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

注意:只有json-filejournald驱动程序使日志可以直接从docker-compose updocker-compose logs获取。 使用任何其他驱动程序将不会打印任何日志。

使用options键为记录驱动程序指定日志记录选项,例如docker run--log-opt选项。

日志记录选项是key-value对。 syslog选项的示例:

driver: "syslog"
options:
  syslog-address: "tcp://192.168.0.42:123"
log_driver

Version 1 file format only. In version 2, use logging.

指定日志驱动程序。默认值为json-file

log_driver: syslog
log_opt

Version 1 file format only. In version 2, use logging.

将记录选项指定为key-value对。 syslog选项的示例:

log_opt:
  syslog-address: "tcp://192.168.0.42:123"
net

Version 1 file format only. In version 2, use network_mode.

网络模式。 使用与docker client --net参数相同的值。 container:...形式可以接受服务名称,而不是容器名称或ID。

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

Version 2 file format and up. In version 1, use net.

网络模式。 使用与docker client --net参数相同的值,以及特殊表单 service:[service name]

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

Version 2 file format and up. In version 1, use net.

要加入的网络, 引用top-level networks key 下的条目。

services:
  some-service:
    networks:
     - some-network
     - other-network
aliases

网络上此服务的别名(备用主机名)。同一网络上的其他容器可以使用服务名称或此别名连接到服务的容器之一。

由于aliases是网络范围的,所以相同的服务可以在不同的网络上具有不同的别名。

注意:网络范围的别名可以由多个容器共享,甚至可以由多个服务共享。 如果是,那么该名称将解析为哪个容器不能保证。

一般格式如下所示。

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
         - alias3
      other-network:
        aliases:
         - alias2

在下面的示例中,提供了三个服务(webworkerdb),以及两个网络(newlegacy)。 db服务在new网络上的主机名dbdatabaselegacy网络中的dbmysql是可达的。

version: '2'

services:
  web:
    build: ./web
    networks:
      - new

  worker:
    build: ./worker
    networks:
    - legacy

  db:
    image: mysql
    networks:
      new:
        aliases:
          - database
      legacy:
        aliases:
          - mysql

networks:
  new:
  legacy:
ipv4_address, ipv6_address

在加入网络时为此服务的容器指定静态IP地址。

顶级网络部分中的相应网络配置必须具有包含每个静态地址的子网和网关配置的ipam块。 如果需要IPv6寻址,则com.docker.network.enable_ipv6驱动程序选项必须设置为true。

version: '2'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      driver: default
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.16.238.1
      - subnet: 2001:3984:3989::/64
        gateway: 2001:3984:3989::1
link_local_ips

Added in version 2.1 file format.

指定link-local IPs。 link-local IPs是属于众所周知的子网并且完全由运营商管理的特殊IP,通常取决于它们被部署的架构。 因此,它们不由docker(IPAM driver)管理。

用法示例:

version: '2.1'
services:
  app:
    image: busybox
    command: top
    networks:
      app_net:
        link_local_ips:
          - 57.123.22.11
          - 57.123.22.13
networks:
  app_net:
    driver: bridge
pid
pid: "host"

将PID模式设置为主机PID模式。 这将打开容器和主机操作系统之间的PID地址空间的共享。 使用此标志启动的容器将能够访问和操作裸机机器命名空间中的其他容器,反之亦然。

ports

公开端口。 指定两个端口(HOST:CONTAINER),或只指定容器端口(将选择随机主机端口)。

注意:当映射HOST:CONTAINER格式的端口时,当使用低于60的容器端口时,您可能会遇到错误的结果,因为YAML将解析格式为xx:yy的数字为六进制(基数60)。 因此,我们建议您始终明确指定端口映射为字符串。

ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"
security_opt

覆盖每个容器的默认标签方案。

security_opt:
  - label:user:USER
  - label:role:ROLE
stop_signal

设置停止容器的备用信号。 默认情况下停止使用SIGTERM。 使用stop_signal设置备用信号将导致停止发送该信号。

stop_signal: SIGUSR1
ulimits

覆盖容器的默认ulimits。 您可以将单个限制指定为整数或soft/hard限制作为映射。

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000
volumes, volume_driver

装载路径或命名卷(可选)指定主机上的路径(HOST:CONTAINER)或访问模式(HOST:CONTAINER:ro)。 对于版本2文件,命名卷需要使用top-level volumes key`指定。 当使用版本1时,Docker Engine将自动创建命名卷(如果不存在)。

您可以在主机上安装相对路径,相对于正在使用的Compose配置文件的目录将相对路径。 相对路径应始终以.要么..

volumes:
  # Just specify a path and let the Engine create a volume
  - /var/lib/mysql

  # Specify an absolute path mapping
  - /opt/data:/var/lib/mysql

  # Path on the host, relative to the Compose file
  - ./cache:/tmp/cache

  # User-relative path
  - ~/configs:/etc/configs/:ro

  # Named volume
  - datavolume:/var/lib/mysql

如果不使用主机路径,则可以指定volume_driver

volume_driver: mydriver

请注意,对于版本2文件,此驱动程序将不适用于named volumes(在使用declaring the volume时,应使用driver选项)。 对于版本1,named volumes和container volumes都将使用指定的驱动程序。

注意:如果您还指定了volume_driver,则不会执行路径扩展。

有关更多信息,请参阅https://docs.docker.com/engine/userguide/dockervolumes/Volume Plugins

volumes_from

从另一个服务或容器装入所有卷,可选择指定只读访问(ro)或读写(rw)。 如果未指定访问级别,则将使用读写。

volumes_from:
 - service_name
 - service_name:ro
 - container:container_name
 - container:container_name:rw

注意container:...格式仅支持版本2文件格式。 在版本1中,您可以使用容器名称,而不将其标记为:

- service_name
- service_name:ro
- container_name
- container_name:rw
cpu_shares, cpu_quota, cpuset, domainname, hostname, ipc, mac_address, mem_limit, memswap_limit, oom_score_adj, privileged, read_only, restart, shm_size, stdin_open, tty, user, working_dir

每个都是一个单一的值,类似于它的docker运行对应。

cpu_shares: 73
cpu_quota: 50000
cpuset: 0,1

user: postgresql
working_dir: /code

domainname: foo.com
hostname: foo
ipc: host
mac_address: 02:42:ac:11:65:43

mem_limit: 1000000000
memswap_limit: 2000000000
privileged: true

oom_score_adj: 500

restart: always read_only: true shm_size: 64M stdin_open: true tty: true 

注意:以下选项仅适用于版本2及更高版本:* oom_score_adj

Volume configuration reference

虽然可以作为服务声明的一部分来即时声明卷,但是此部分允许您创建可以跨多个服务重用的命名卷(不依赖volumes_from),并且可以使用docker命令行轻松检索和检查 或API。 有关更多信息,请参阅docker volume子命令文档。

driver

指定应为此卷使用哪个卷驱动程序。 默认为local。 如果驱动程序不可用,Docker Engine将返回错误。

driver: foobar
driver_opts

将选项列表指定为要传递给此卷的驱动程序的key-value pairs。 这些选项是驱动程序相关的 - 请参阅驱动程序文档以获取更多信息。 可选的。

driver_opts:
   foo: "bar"
   baz: 1
external

如果设置为true,则指定该卷已在Compose外部创建。 docker-compose up不会尝试创建它,并且如果它不存在将会引发一个错误。

external不能与其他卷配置键(driverdriver_opts)一起使用。

在下面的示例中,不是尝试创建名为[projectname] _data的卷,Compose将查找现有的卷,简单地称为数据,并将其挂载到db服务的容器中。

version: '2'

services:
  db:
    image: postgres
    volumes:
      - data:/var/lib/postgresql/data

volumes:
  data:
    external: true

您还可以指定卷的名称与用于在Compose文件中引用它的名称:

volumes:
  data:
    external:
      name: actual-name-of-volume
labels

Added in version 2.1 file format.

使用Docker labels向容器添加元数据。 您可以使用数组或字典。

建议您使用反向DNS符号来防止您的标签与其他软件使用的标签冲突。

labels:
  com.example.description: "Database volume"
  com.example.department: "IT/Ops"
  com.example.label-with-empty-value: ""

labels:
  - "com.example.description=Database volume"
  - "com.example.department=IT/Ops"
  - "com.example.label-with-empty-value"

Network configuration reference

顶层网络键允许您指定要创建的网络。 有关Compose使用Docker网络功能的完整说明,请参阅Networking guide

driver

指定应为此网络使用哪个驱动程序。

默认驱动程序取决于您使用的Docker引擎是如何配置的,但在大多数情况下,它将是单个主机上的bridge和Swarm上的overlay

如果驱动程序不可用,Docker Engine将返回错误。

driver: overlay
driver_opts

指定选项列表作为要传递给此网络驱动程序的键值对。 这些选项是driver-dependent - consult的驱动程序文档的更多信息。 可选的。

driver_opts:
    foo: "bar"
    baz: 1
enable_ipv6

Added in version 2.1 file format.

在此网络上启用IPv6网络。

ipam

指定自定义IPAM配置。 这是一个具有多个属性的对象,每个属性都是可选的:

  • driver:自定义IPAM驱动程序,而不是默认值。
  • config:具有零个或多个配置块的列表,每个配置块包含以下任意键:
    • subnet: 表示网段的CIDR格式的子网
    • ip_range: 从中分配容器IPs的IP范围
    • gateway: 主子网的IPv4或IPv6网关
    • aux_addresses:网络驱动程序使用的辅助IPv4或IPv6地址,作为从主机名到IP地址的映射
  • options: 作为键值映射的驱动特定选项。

A full example:

ipam:
  driver: default
  config:
    - subnet: 172.28.0.0/16
      ip_range: 172.28.5.0/24
      gateway: 172.28.5.254
      aux_addresses:
        host1: 172.28.1.5
        host2: 172.28.1.6
        host3: 172.28.1.7
  options:
    foo: bar
    baz: "0"
internal

Version 2 file format and up.

默认情况下,Docker还将桥接网络连接到它以提供外部连接。 如果要创建外部隔离的覆盖网络,您可以将此选项设置为true。

labels

Added in version 2.1 file format.

使用Docker标签向容器添加元数据。 您可以使用数组或字典。

建议您使用反向DNS符号来防止您的标签与其他软件使用的标签冲突。

labels:
  com.example.description: "Financial transaction network"
  com.example.department: "Finance"
  com.example.label-with-empty-value: ""

labels:
  - "com.example.description=Financial transaction network"
  - "com.example.department=Finance"
  - "com.example.label-with-empty-value"
external

如果设置为true,则指定此网络已在Compose之外创建。 docker-compose up不会尝试创建它,并且如果它不存在将会引发一个错误。

外部不能与其他网络配置键(driverdriver_optsgroup_addipaminternal)一起使用。

在下面的示例中,proxy是到外部世界的网关。 而不是尝试创建一个名为[projectname] _outside的网络,Compose将查找一个现有的网络,简单地调用外outside并连接outside服务的容器。

version: '2'

services:
  proxy:
    build: ./proxy
    networks:
      - outside
      - default
  app:
    build: ./app
    networks:
      - default

networks:
  outside:
    external: true

您还可以单独指定网络的名称,与用于在Compose文件中引用它的名称:

networks:
  outside:
    external:
      name: actual-name-of-network

Versioning

目前有三个版本的Compose文件格式:

  • 版本1,传统格式。 这是通过省略YAML根目录下的版本键来指定的。
  • 版本2,推荐格式。 这是使用版本:’2’条目在YAML的根目录指定。
  • 版本2.1,升级超过版本2,利用了Docker Engine的最新特性。 使用版本:“2.1”条目指定YAML根目录。

要将项目从版本1移动到2,请参阅升级部分。

注意:如果您使用多个Compose文件或扩展服务,每个文件必须是相同的版本 - 您不能在单个项目中混合版本1和2。

根据您使用的版本,有几点不同:

  • 结构和允许的配置键
  • 必须运行的最低Docker Engine版本
  • 撰写关于网络的行为这些差异如下所述。
Version 1

未声明版本的组合文件被视为“版本1”。 在这些文件中,所有服务都在文档的根目录处声明。

版本1由Compose到1.6.x支持。 它将在未来的Compose版本中被弃用。

版本1文件无法声明命名卷,网络或构建参数。

例:

web:
  build: .
  ports:
   - "5000:5000"
  volumes:
   - .:/code
  links:
   - redis
redis:
  image: redis
Version 2

使用版本2语法的撰写文件必须指示文档根目录下的版本号。 所有服务必须在服务键下声明。

Compose 1.6.0+支持版本2文件,并需要版本1.10.0+的Docker引擎。

可以在volumes键下声明命名卷,并且可以在networks关键字下声明网络。

简单示例:

version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: redis

一个更广泛的例子,定义卷和网络:

version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    networks:
      - front-tier
      - back-tier
  redis:
    image: redis
    volumes:
      - redis-data:/var/lib/redis
    networks:
      - back-tier
volumes:
  redis-data:
    driver: local
networks:
  front-tier:
    driver: bridge
  back-tier:
    driver: bridge
Version 2.1

升级版本2,引入仅适用于Docker Engine版本1.12.0+的新参数

引入以下附加参数:* link_local_ips* isolation* labels for volumes and networks

Upgrading

在大多数情况下,从版本1移动到2是一个非常简单的过程:

  1. 将整个文件缩进一级,并在顶部放置一个services:键。
  2. 添加一个version: '2'行在文件的顶部。

如果您使用特定的配置功能,则更复杂:* dockerfile: This now lives under the build key:

  build:
  context: .
  dockerfile: Dockerfile-alternate
  • log_driver, log_opt: These now live under the logging key:logging:driver: syslogoptions:syslog-address: "tcp://192.168.0.42:123"

  • 与环境变量的链接:如环境变量引用中所述,由链接创建的环境变量已经过时了一段时间。 在新的Docker网络系统中,它们已被删除。 您应该直接连接到相应的主机名,或者自己设置相关的环境变量,使用link hostname:“`web:links:

    • dbenvironment:
    • DB_PORT=tcp://db:5432“`
  • external_links:Compose在运行版本2项目时使用Docker网络,因此链接的行为略有不同。 特别地,两个容器必须共同连接到至少一个网络,以便进行通信,即使明确地链接在一起。将外部容器连接到应用程序的默认网络,或者将外部容器和服务的容器都连接到外部网络。

  • net: 这现在由network_mode替换:

    net: host    ->  network_mode: host
    net: bridge  ->  network_mode: bridge
    net: none    ->  network_mode: none
    

    如果你使用 net: "container:[service name]", 用 network_mode: "service:[service name]" 替换。

    net: "container:web"  ->  network_mode: "service:web"
    

    如果你使用 net: "container:[container name/id]", 值可以不变。

    net: "container:cont-name"  ->  network_mode: "container:cont-name"
    net: "container:abc12345"   ->  network_mode: "container:abc12345"
    
  • 具有命名卷的卷:这些必须现在必须在Compose文件的顶级卷部分中显式声明。 如果服务装载称为数据的命名卷,则必须在顶层卷部分中声明数据卷。 整个文件可能如下所示:

    version: '2'
    services:
    db:
    image: postgres
    volumes:
      - data:/var/lib/postgresql/data
    volumes:
    data: {}
    

    默认情况下,Compose会创建一个以项目名称为前缀的卷。 如果你想要它只是被称为数据,声明它为外部

    volumes:
    data:
    external: true
    

Variable substitution

您的配置选项可以包含环境变量。 Compose使用运行docker-compose的shell环境中的变量值。 例如,假设shell包含EXTERNAL_PORT = 8000,并且您提供此配置:

web:
  build: .
  ports:
    - "${EXTERNAL_PORT}:5000"

当使用此配置运行docker-compose up时,Compose会在shell中查找EXTERNAL_PORT环境变量并将其值代入。在本示例中,Compose在创建Web容器之前将端口映射解析为“8000:5000”

如果未设置环境变量,则Compose将替换为空字符串。 在上面的示例中,如果未设置EXTERNAL_PORT,则端口映射的值为:5000(这当然是无效的端口映射,并且将在尝试创建容器时导致错误)。

支持$VARIABLE${VARIABLE}语法。 此外,当使用2.1文件格式时,可以使用典型的shell语法提供内联默认值:* 如果VARIABLE在环境中未设置或为空,${VARIABLE:-default}将评估为默认值。* 只有在环境中未设置VARIABLE的情况下,${VARIABLE-default}才会评估为默认值。

不支持其他扩展的shell样式功能,例如${VARIABLE/foo/bar}

当您的配置需要一个字母美元符号时,您可以使用$$(双美元符号)。 这也防止了Compose内插值,所以$$允许你引用你不想由Compose处理的环境变量。

web:
  build: .
  command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"

如果您忘记并使用单个美元符号($),Compose将该值解释为环境变量并将警告您:

未设置VAR_NOT_INTERPOLATED_BY_COMPOSE。 替换空字符串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值