Dockerfile参考(8) – CMD设置运行容器时执行的命令

CMD指令有三种形式:

  • CMD [“executable”,”param1″,”param2″] [exec形式,这是首选形式]
  • CMD [“param1″,”param2”] [作为ENTRYPIOINT的默认参数]
  • CMD command param1 param2 [shell形式]
  • Dockerfile只能使用一个CMD指令。如果你使用了多个CMD那么Docker仅使用最后一个。
    CMD的主要作用是为执行容器提供默认值。这些默认值可以包括一个可执行程序,或省略可执行程序(这种情况下需要指定一个ENTRYPOINT指令)。

    注意:如果CMD用来提供ENTRYPOINT的默认参数,那么CMD和ENTRYPOINT指令应该使用JSON数组的格式。

    注意:exec形式使用了JSON数组,意味着字符外使用双引号而不是单引号。

    不论使用是的shell或exec格式,CMD指令设置了当运行镜像时要执行的命令。
    如果使用CMD的shell形式,那么将在/bin/sh -c执行:

    1. FROM ubuntu
    2. CMD echo "This is a test." | wc –

    如果你想不调用shell运行你的,那么你必须以JSON数组表示你的命令并给出这个命令的完整路径。这个数组形式是CMD的首先格式。额外的参数必须单独地使用一个数组的字符串表示:

    1. FROM ubuntu
    2. CMD ["/usr/bin/wc","–help"]

    如果你想每次容器都是执行相同的执行程序,那么你应该考虑ENTRYPOINT和CMD一起使用。
    如果用户在docker run指定参数,那么将会覆盖CMD指定的默认参数。

    注意:不要把RUN和CMD搞混了。RUN实际上是在构建镜像时执行命令并提交执行结果到镜像;而CMD在构建期间不会执行任何命令,只是为镜像预先设置运行时容器时运行的命令或参数。

    Dockerfile参考(7) – RUN执行命令指令

    RUN指令有两种形式:

  • RUN [shell形式,运行在shell的命令,默认是Linux上的/bin/sh -c或windows的cmd /S /C]
  • RUN [“executable”, “param1”, “param2”][exec形式]
  • RUN指令将在当前镜像层上面的一个新数据层执行命令并提交其结果。这个新提交的镜像层将用于Dockerfile的下一步。
    分层RUN指令和生成提交符合Docker的核心概念,其中提交成本低,可以从镜像历史中的任何点创建容器,就像源代码控制一样。
    exec形式避免了shell字符的模糊处理,并且可以在没有特定shell的base镜像上使用RUN指令。
    shell形式中默认的shell可以使用SHELL命令更改。
    在shell形式中你可以使用反斜杠在下一行继续这个RUN指令。例如下面两行:

    1. RUN /bin/bash -c ‘source $HOME/.bashrc;
    2. echo $HOME’

    两行相当于:

    1. RUN /bin/bash -c ‘source $HOME/.bashrc; echo $HOME’

    注意:要在exec形式中使用不同的shell,而不是/bin/sh,传递想用的shell即可,如,[“/bin/bash”, “-c”, “echo hello”]

    注意:exec形式是接一个JSON数组,意味着在单词之外使用双引号而不是单引号。

    注意:不像shell形式,exec形式不会调用一个shell再执行命令。意味着常规shell处理不会发生。例如,RUN [ “echo”, “$HOME” ]不会替换$HOME为家目录。如果你想处理此情况,可以直接使用shell形式或直接执行一个shell。如RUN [ “sh”, “-c”, “echo $HOME” ]。

    注意:在JSON格式中,有必要转义反斜杠,特别是windows中使用反斜杠作为路径分隔符的情况。[“c:windowssystem32tasklist.exe”] 会视为shell形式,因为这不是一个有效的JSON格式,正确的语法是RUN [“c:\windows\system32\tasklist.exe”]。

    RUN指令的缓存不会在下一次构建镜像时自动失效。一个指令的缓存如RUN apt-get dist-upgrade -y会在下一次构建中重用。可以使用–no-cache参数来使RUN指令的缓存失效,例如docker build –no-cache。

    Dockerfile参考(6) – FROM和MAINTAINER指令

    FROM

    1. FROM <image>

    1. FROM <image>:<tag>

    1. FROM <image>@<digest>

    FROM指令为随后的指令设置一个Base Image。因此,一个有效的Dockerfile的第一个指令必须是FROM。镜像可以是任意有效的镜像 – 这个很容易从公共仓库拉取一个镜像。

  • FROM必须是Dockerfile中的首个非注释指令。
  • FROM可以在单个Dockerfile中出现多次,这样可以创建多个镜像。只需记下在每个新的FROM命令之前由提交输出的最后一个图像ID。
  • tag或digest值是可选的。如果都不指定,那么默认是latest。如果找不到tag的值将返回错误。
  • MAINTAINER

    1. MAINTAINER <name>

    MAINTAINER指令允许你设置生成这个镜像的作者。

    Dockerfile参考(5) – .dockerignore文件

    在docker CLi发送上下文到docker daemon之前,它首先先在上下文的根目录查找名为.dockerignore的文件。如果这个文件存在,CLI则更改上下文来排除与这文件里的模式匹配的文件和目录。这帮助避免了发送不必要的大的或敏感的文件和目录到daemon,以及有可能使用ADD或COPY把不必要的文件添加到镜像。
    CLI解析.dockerignore为以行为分隔的模式列表,类似于Unix shells的golbs文件。基于匹配的目的,上下文的根目录可以是工作目录或根目录。例如,/foo/bar和foo/bar模式都是排除PATH或URL git仓库根目录的子目录foo下的bar文件。
    如果.dockerignore中的一行以#开始,那么这行视为注释,会以CLI解析前忽略。
    例如:

    1. # comment
    2.     */temp*
    3.     */*/temp*
    4.     temp?

    行为解释如下:

  • # comment:忽略
  • <*/temp*:排除在任意根目录的子目录下以temp开始的文件和目录。例如,/somedir/temporary.txt文件和/somedir/temp目录都被排除。
  • */*/temp*:排除从根目录两级目录的子目录下以temp开始的文件或目录。例如,/somedir/subdir/temporary.txt文件会被排除。
  • temp?:排除temp后加一个字符的文件或目录。如/tempa和/tempb被排除。
  • 使用Go的filepath.Match规则完成匹配。除了Go的filepath.Match规则,docker也支持一个特殊的通配符**,用来匹配任意数量的目录。如**/*.go将排除在所有目录中以.go后缀的文件,包括根目录。
    以!开始的行表示与排除相反的动作,即包括。如下:

    1. *.md
    2.     !README.md

    除了README.md,其它的.md文件排除。
    放置!例外规则影响的行为:.dockerignore的最后行匹配的文件决定是否是包含或排除。如下:

    1. *.md
    2.     !README*.md
    3.     README-secret.md

    除了README markdown文件(不含README-secret.md),其它的markdown文件包括全都排除。
    再看一个例子:

    1. *.md
    2.     README-secret.md
    3.     !README*.md

    包括所有的README文件。中间的行没有影响是因为!README*.md匹配了README-secret.md。
    你甚至可以使用.dockerignore文件来排除Dockerfile和.dockerignore文件。这些排除的文件仍然会发送到daemon,因为需要它们来工作。不过ADD和COPY命令不再复制它们到镜像。
    最后,你可能想指定包括一些文件,而不是排除。那么可以在第一行输入*,随后的行使用!来包括。

    注意:由于历史原因,模式.会被忽略。

    Dockerfile参考(4) – 使用环境变量

    由EVN指令声明的环境变量也可以用在Dockerfile的一些指令中作为变量使用。转义符也将类似变量的语法转义为语句。
    在Dockerfile引用环境变量可以使用$variable_name或${variable_name}。它们是等同的,其中大括号的变量是用在没有空格的变量名中的,如${foo}_bar。
    ${variable_name}变量也支持一些标准的bash修饰符,如:

  • ${variable:-word}表示如果variable设置了,那么结果就是设置的值。否则设置值为word
  • ${variable:+word}表示如果variable设置了,那么结果是word值,否则为空值。
  • word可以是任意的字符,包括额外的环境变量。
    转义符可以添加在变量前面:$foo or ${foo},例如,会分别转换为$foor和${foo}。
    示例:

    1. FROM busybox
    2. ENV foo /bar
    3. WORKDIR ${foo}   # WORKDIR /bar
    4. ADD . $foo       # ADD . /bar
    5. COPY $foo /quux # COPY $foo /quux

    环境变量支持在下面的指令中使用:

  • ADD
  • COPY
  • ENV
  • EXPOSE
  • LABEL
  • USER
  • WORKDIR
  • VOLUME
  • STOPSIGNAL
  • 也包括:

  • ONBUILD
  • 注意:1.4之前的版本,ONBUILD指令不支持环境变量,即使是与上面列出的指令一起使用。

    环境变量的替换在整个命令使用的值是一样的。例如:

    1. ENV abc=hello
    2. ENV abc=bye def=$abc
    3. ENV ghi=$abc

    def的值是hello,不是bye,不过,ghi的值为bye,因为设置abc为bye的命令与设置ghi命令不同。

    Dockerfile参考(3) – 解释器指令escape

    解释器指令是可选的,并影响Dockerfile随后行的处理方式。解释器指令不会添加新层到镜像,也不会显示在构建步骤中。解释器指令的编写格式是一种特定的注释格式# directive=value。一个指令只能用一次。
    一旦注释,空行或构建器指令已经被处理,Docker不再寻找解析器指令。相反,它将格式化为解析器指令的任何内容视为注释,并且不尝试验证它是否可能是解析器指令。因此,所有解析器指令必须位于Dockerfile的最顶端。
    解析器指令不区分大小写。不过,约定使用小写。也约定解释器指令后包括一个新空行。解析器指令不支持行连续字符。
    由于这些规则,下面的示例都是无效的:
    由于使用了行连续字符无效:

    1. # direc
    2. tive=value

    由于出现两次相同的解释器指令:

    1. # directive=value1
    2. # directive=value2
    3.  
    4. FROM ImageName

    由于出现在构建指令后,所以视为注释:

    1. FROM ImageName
    2. # directive=value

    由于出现在不是解释器指令的注释后面,视为一个注释:

    1. # About my dockerfile
    2. FROM ImageName
    3. # directive=value

    由于不被识别,未知的指令视为一个注释。此外由于出现在不是解释器指令的注释后面,一个已知的指令也视为注释。

    1. # unknowndirective=value
    2. # knowndirective=value

    解析器指令中允许使用非换行符空格。因此,下面的指令视为同样的:

    1. #directive=value
    2. # directive =value
    3. #   directive= value
    4. # directive = value
    5. #     dIrEcTiVe=value

    目前支持的解释器指令有:

  • escape
  • escape

    格式为:

    1. # escape= (backslash)

    1. # escape=` (backtick)

    escape指令用于设置在Dockerfile中转义使用的字符。如果不指定,默认的转义字符是。
    转义字符用来转义一行中的字符,也可以转义一个新行。这就允许Dockerfile的指令跨越多行。注意,不管escape解析器指令是否包括在Dockerfile中,除了在行尾转义新行 RUN命令中不进行字符转义。
    设置转义字符`对于windows上使用Dockerfile非常有用,因为默认的是目录路径的分隔符。而`与Windows PowerShell使用的转义字符一致。
    看下下面的在windows Dockerfile的示例,不是很显然地看出错误。第二行行尾的第二个解释为转义新行,而不是第一个的转义目标。结果是这个Dockerfile的第2行和第3行合并为一行处理:

    1. FROM windowsservercore
    2. COPY testfile.txt c:\
    3. RUN dir c:

    构建时输出:

    1. PS C:John> docker build -t cmd .
    2. Sending build context to Docker daemon 3.072 kB
    3. Step 1 : FROM windowsservercore
    4.  —> dbfee88ee9fd
    5. Step 2 : COPY testfile.txt c:RUN dir c:
    6. GetFileAttributesEx c:RUN: The system cannot find the file specified.
    7. PS C:John>

    上面的一个解决方法是使用/作为COPY和dir的路径分隔符。不过这个语法最好的结果是只会由于不是windows原生的分隔符感到混乱,最糟糕的情况是会导致错误,因为windows不是所有的命令都支持这个分隔符。
    所以最好的解决方法是使用excape解释器指令来指令`作为分隔符:

    1. # escape=`
    2.  
    3. FROM windowsservercore
    4. COPY testfile.txt c:
    5. RUN dir c:

    结果:

    1. PS C:John> docker build -t succeeds –no-cache=true .
    2. Sending build context to Docker daemon 3.072 kB
    3. Step 1 : FROM windowsservercore
    4.  —> dbfee88ee9fd
    5. Step 2 : COPY testfile.txt c:
    6.  —> 99ceb62e90df
    7. Removing intermediate container 62afbe726221
    8. Step 3 : RUN dir c:
    9.  —> Running in a5ff53ad6323
    10.  Volume in drive C has no label.
    11.  Volume Serial Number is 1440-27FA
    12.  
    13.  Directory of c:
    14.  
    15. 03/25/2016  05:28 AM    <DIR>          inetpub
    16. 03/25/2016  04:22 AM    <DIR>          PerfLogs
    17. 04/22/2016  10:59 PM    <DIR>          Program Files
    18. 03/25/2016  04:22 AM    <DIR>          Program Files (x86)
    19. 04/18/2016  09:26 AM                 4 testfile.txt
    20. 04/22/2016  10:59 PM    <DIR>          Users
    21. 04/22/2016  10:59 PM    <DIR>          Windows
    22.                1 File(s)              4 bytes
    23.                6 Dir(s)  21,252,689,920 bytes free
    24.  —> 2569aa19abef
    25. Removing intermediate container a5ff53ad6323
    26. Successfully built 2569aa19abef
    27. PS C:John>

    Dockerfile参考(2) – 格式

    下面是Dockerfile的格式:

    1. # Comment
    2. INSTRUCTION arguments

    instruction指令是不区分大小写的,不过一般约定使用大写字符以与参数区分开来。
    docker按顺序执行Dockerfile中的指令。第一个指令必须是FROM,用于指定从哪个Base Image构建镜像。
    Docker把以#开头的行视为注释,除非该行是一个有效的解释器指令。#标志在行中的其它地方视为一个参数,如:

    1. # Comment
    2. RUN echo ‘we are running some # of cool things’

    注释中不支持行连续字符。

    Dockerfile参考(1) – 用法

    docker build命令从Dockerfile文件和上下文构建一个镜像。构建的上下文是一个指定的PATH或URL位置。PATH是你本地文件系统的一个目录。URL是git仓库地址。
    上下文是递归处理的。所以PATH包括所有的子目录,URL包括仓库和它的子模块。下面是使用当前目录作为上下文的简单build命令:

    1. $ docker build .
    2. Sending build context to Docker daemon  6.51 MB

    build命令来docker daemon运行,不是由CLI。build进程的第一件事是递归发送整个上下文给daemon。大多数情况下,最好使用一个空的目录作为上下文并放置Dockerfile到此目录。只添加构建Dockerfile时所需的文件。

    警告:不要使用root目录/作为PATH,因为它会导致build传递你硬盘的所有内容到docker daemon。

    Dockerfile包括了一系列用于构建镜像的指令,例如COPY指令。为了提高构建性能,可以通过添加.dockerignore文件到上下文目录来排除文件和目录。
    通常称为Dockerfile的Dockerfile文件放置在上下文的根目录。你可以将docker build与-f参数一起使用来指向你文件系统的任何位置的Dockerfile。

    1. $ docker build -f /path/to/a/Dockerfile .

    可以使用-t参数指定保存新镜像的仓库和标签:

    1. $ docker build -t shykes/myapp .

    要标记镜像到多个仓库,可以在build命令中使用多个-t参数:

    1. $ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

    docker daemon一个接一个运行Dockerfile中的指令,在最后生成新镜像之前,如果需要,将提交每一个指令的结果到新镜像。docker daemon会自动清理你发送过来的上下文。
    注意每个指令都是独立运行的,所以RUN cd /tmp不会对下一个指令有任何影响。
    如果有可能,docker会重用镜像缓存来加速docker build进程。在控制台输出中使用到缓存时将显示Using cache消息。如:

    1. $ docker build -t svendowideit/ambassador .
    2. Sending build context to Docker daemon 15.36 kB
    3. Step 1 : FROM alpine:3.2
    4.  —> 31f630c65071
    5. Step 2 : MAINTAINER [email protected]
    6.  —> Using cache
    7.  —> 2a1c91448f5f
    8. Step 3 : RUN apk update &&      apk add socat &&        rm -r /var/cache/
    9.  —> Using cache
    10.  —> 21ed6e7fbb73
    11. Step 4 : CMD env | grep _TCP= | (sed ‘s/.*_PORT_([0-9]*)_TCP=tcp://(.*):(.*)/socat -t 100000000 TCP4-LISTEN:1,fork,reuseaddr TCP4:2:3 &/’ && echo wait) | sh
    12.  —> Using cache
    13.  —> 7ea8aef582cc
    14. Successfully built 7ea8aef582cc

    创建MongoDB Docker镜像

    简介

    本文我们准备学习如何构建MongoDB Docker镜像。以及如何推送镜像到Docker Hub registr和与其他人共享。
    使用docker和容器部署mongodb实例有几个好处:

  • 易于维护,高度可配置的MongoDB实例
  • 毫秒级运行和启动
  • 可共享镜像
  • 创建MongoDB Dockerfile

    我们来创建Dockerfile并开始构建它:
    以下说明的可选的,不过在Dockerfile开头添加注释可以说明它的目的:

    1. # Dockerizing MongoDB: Dockerfile for building MongoDB images
    2.     # Based on ubuntu:latest, installs MongoDB following the instructions from:
    3.     # http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/

    我们使用从Docker Hub最新的Ubuntu版本来构建镜像。

    1. # Format: FROM    repository[:version]
    2. FROM       ubuntu:latest

    然后声明此Dockerfile的维护者:

    1. # Format: MAINTAINER Name <[email protected]>
    2. MAINTAINER M.Y. Name <[email protected]>

    导入MongoDB公共GPG密钥。然后创建一个MongoDB仓库文件。

    1. # Installation:
    2. # Import MongoDB public GPG key AND create a MongoDB list file
    3. RUN apt-key adv –keyserver hkp://keyserver.ubuntu.com:80 –recv 7F0CEB10
    4. RUN echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.0.list

    完成这些初始准备后我们就可以更新软件包并安装MongoDB。

    1. # Update apt-get sources AND install MongoDB
    2. RUN apt-get update && apt-get install -y mongodb-org

    MongoDB需要一个数据目录。

    1. # Create the MongoDB data directory
    2. RUN mkdir -p /data/db

    最后设置ENTRYPOINT来让docker从镜像运行一个容器时执行这个ENTRYPOINT。对于端口,使用EXPOSE暴露。

    1. # Expose port 27017 from the container to the host
    2. EXPOSE 27017
    3.  
    4. # Set usr/bin/mongod as the dockerized entry-point application
    5. ENTRYPOINT ["/usr/bin/mongod"]

    构建MongoDB Docker镜像

    开始构建镜像。

    1. # Format: docker build –tag/-t <user-name>/<repository> .
    2. # Example:
    3. $ docker build –tag my/repo .

    推送MongoDB镜像到Docker Hub

    首先登录到docker hub。

    1. # Log-in
    2. $ docker login
    3.  
    4. Username:
    5. ..

    开始推送:

    1. # Push the image
    2. # Format: docker push <user-name>/<repository>
    3. $ docker push my/repo
    4.  
    5. The push refers to a repository [my/repo] (len: 1)
    6. Sending image list
    7. Pushing repository my/repo (1 tags)
    8. ..

    使用MongoDB镜像

    使用刚构建好的MongoDB镜像,我们可以运行一个或多个MongoDB实例。

    1. # Basic way
    2. # Usage: docker run –name <name for container> -d <user-name>/<repository>
    3. $ docker run -p 27017:27017 –name mongo_instance_001 -d my/repo
    4.  
    5. # Dockerized MongoDB, lean and mean!
    6. # Usage: docker run –name <name for container> -d <user-name>/<repository> –noprealloc –smallfiles
    7. $ docker run -p 27017:27017 –name mongo_instance_001 -d my/repo –smallfiles
    8.  
    9. # Checking out the logs of a MongoDB container
    10. # Usage: docker logs <name for container>
    11. $ docker logs mongo_instance_001
    12.  
    13. # Playing with MongoDB
    14. # Usage: mongo –port <port you get from `docker ps`>
    15. $ mongo –port 27017
    16.  
    17. # If using docker-machine
    18. # Usage: mongo –port <port you get from `docker ps`>  –host <ip address from `docker-machine ip VM_NAME`>
    19. $ mongo –port 27017 –host 192.168.59.103

    如果需要在一个主机运行多个实例,需要映射不同的端口。

    1. # Start two containers and map the ports
    2. $ docker run -p 28001:27017 –name mongo_instance_001 -d my/repo
    3.  
    4. $ docker run -p 28002:27017 –name mongo_instance_002 -d my/repo
    5.  
    6. # Now you can connect to each MongoDB instance on the two ports
    7. $ mongo –port 28001
    8.  
    9. $ mongo –port 28002

    Docker管理指南(5) – 使用systemd控制和配置Docker

    许多Linux发行版本使用systemd来启动docker daemon。本文介绍如何自定义docker设置的一些示例。

    启动docker daemon

    docker安装后,开始启动docker daemon。

    1. $ sudo systemctl start docker
    2. # 或旧的发行版本,使用
    3. $ sudo service docker start

    设置docker开机启动:
    $ sudo systemctl enable docker
    # 或旧的发行版本,使用
    $ sudo chkconfig docker on

    自定义docker daemon选项

    有几种方法来配置docker daemon的参数和环境变量。
    推荐的方法是使用systemd的drop-in文件。这些是在/etc/systemd/system/docker.service.d目录的命名为.conf的本地文件。也可以放置在/etc/systemd/system/docker.service文件,会覆盖默认的/lib/systemd/system/docker.service文件。
    不过如果你使用包管理器安装了docker,那么可能EnvironmentFile已经存在,为了向后兼容,在/etc/systemd/system/docker.service.d放置一下.conf文件,内容如下:

    1. [Service]
    2. EnvironmentFile=-/etc/sysconfig/docker
    3. EnvironmentFile=-/etc/sysconfig/docker-storage
    4. EnvironmentFile=-/etc/sysconfig/docker-network
    5. ExecStart=
    6. ExecStart=/usr/bin/dockerd $OPTIONS
    7.           $DOCKER_STORAGE_OPTIONS
    8.           $DOCKER_NETWORK_OPTIONS
    9.           $BLOCK_REGISTRY
    10.           $INSECURE_REGISTRY

    检查docker.service是否使用了EnvironmentFile:

    1. $ systemctl show docker | grep EnvironmentFile
    2.  
    3. EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)

    或者找出service文件放置的位置:

    1. $ systemctl show –property=FragmentPath docker
    2.  
    3. FragmentPath=/usr/lib/systemd/system/docker.service
    4.  
    5. $ grep EnvironmentFile /usr/lib/systemd/system/docker.service
    6.  
    7. EnvironmentFile=-/etc/sysconfig/docker

    你可以使用一个覆盖文件来自定义docker daemon选项。位于/usr/lib/systemd/system或/lib/systemd/system目录的文件包含了默认的选项,不应该去编辑它。

    运行时目录和存储驱动

    你可能想控制docker镜像,容器和volumes占用的硬盘空间,这个可以把它们移动到一个单独的分区。
    在这个示例中,我们假设你的docker.service文件类似如下:

    1. [Unit]
    2. Description=Docker Application Container Engine
    3. Documentation=https://docs.docker.com
    4. After=network.target
    5.  
    6. [Service]
    7. Type=notify
    8. # the default is not to use systemd for cgroups because the delegate issues still
    9. # exists and systemd currently does not support the cgroup feature set required
    10. # for containers run by docker
    11. ExecStart=/usr/bin/dockerd
    12. ExecReload=/bin/kill -s HUP $MAINPID
    13. # Having non-zero Limit*s causes performance problems due to accounting overhead
    14. # in the kernel. We recommend using cgroups to do container-local accounting.
    15. LimitNOFILE=infinity
    16. LimitNPROC=infinity
    17. LimitCORE=infinity
    18. # Uncomment TasksMax if your systemd version supports it.
    19. # Only systemd 226 and above support this version.
    20. #TasksMax=infinity
    21. TimeoutStartSec=0
    22. # set delegate yes so that systemd does not reset the cgroups of docker containers
    23. Delegate=yes
    24. # kill only the docker process, not all processes in the cgroup
    25. KillMode=process
    26.  
    27. [Install]
    28. WantedBy=multi-user.target

    我们可以在/etc/systemd/system/docker.service.d目录放置一个drop-in文件,包含如下内容:

    1. [Service]
    2. ExecStart=
    3. ExecStart=/usr/bin/dockerd –graph="/mnt/docker-data" –storage-driver=overlay

    可以在这个文件设置其它的环境变量,例如,HTTP_PROXY。
    要更改ExecStart配置,可以在一行空的ExecStart的下一行放置一个新的ExecStart:

    1. [Service]
    2. ExecStart=
    3. ExecStart=/usr/bin/dockerd –bip=172.17.42.1/16

    HTTP proxy

    此示例覆盖了默认的docker.service文件。
    如果你的主机需要通过Http代理服务器连网,你需要在docker systemd service文件配置一个http代理。
    1.为docker service创建一个systemd drop-in目录:

    1. $ mkdir /etc/systemd/system/docker.service.d

    2.创建/etc/systemd/system/docker.service.d/http-proxy.conf文件,添加HTTP_PROXY环境变量:

    1. [Service]
    2. Environment="HTTP_PROXY=http://proxy.example.com:80/"

    3.可以使用NO_PROXY指定不需要代理的一些地址:

    1. Environment="HTTP_PROXY=http://proxy.example.com:80/" "NO_PROXY=localhost,127.0.0.1,docker-registry.somecorporation.com"

    4.重载配置

    1. $ sudo systemctl daemon-reload

    5.验证配置是否已经加载:

    1. $ systemctl show –property=Environment docker
    2. Environment=HTTP_PROXY=http://proxy.example.com:80/

    6.重启docker

    1. $ sudo systemctl restart docker

    手动创建systemd单元文件

    如果你不是使用包管理器安装的docker,但想整合docker进systemd便于管理。可以从https://github.com/docker/docker/tree/master/contrib/init/systemd下载两个单元文件安装到/etc/systemd/system目录即可。