使用Docker或者docker-compose搭建gitlab

一. 直接下载docker-ce

1. 拉取gitlab/gitlab-ce

Randy:~ Randy$ docker pull gitlab/gitlab-ce
Using default tag: latest

2. 运行gitlab/gitlab-ce

Randy:~ Randy$ docker run -d --publish 8443:443 --publish 8001:80 --publish 8022:22 --name gitlab-randy --restart always gitlab/gitlab-ce

其中使用publish参数映射host主机上的8443到docker-ce上面的443端口,并制定使用bash。此处可以使用–volume参数来指定docker-ce中的文件到host主机上的路径以便于升级,此处仅作为测试使用。

3. 验证http://127.0.0.1:8001/可以登录,首次登录需要修改密码

二. 使用Docker-compose方式

这种方式是比较灵活,也是官方推荐的安装方式。实际上就是把启动docker的参数配置到文件中,并通过docker-compose up调用。步骤如下:

1. 下载docker-compose.yml文件

wget https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml
[root@randysun ~]# wget https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml
--2017-08-06 11:36:43--  https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.72.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.72.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3836 (3.7K) [text/plain]
Saving to: ‘docker-compose.yml’

100%[============================================================================>] 3,836       --.-K/s   in 0s      

2017-08-06 11:36:44 (64.7 MB/s) - ‘docker-compose.yml’ saved [3836/3836]

2. 在第一步中下载好的文件路径下运行docker-compose up

[root@randysun ~]# docker-compose up
Creating network "root_default" with the default driver
Pulling postgresql (sameersbn/postgresql:9.6-2)...
9.6-2: Pulling from sameersbn/postgresql
c60055a51d74: Downloading [=>                                                 ]  1.615MB/65.69MB
755da0cdb7d2: Download complete
969d017f67e6: Download complete
37c9a9113595: Download complete
a3d9f8479786: Download complete
e43d9de53575: Downloading [==================>                                ]  1.754MB/4.702MB
cddf24084b61: Download complete
f23b95c5f17c: Waiting
3965edbc705f: Waiting
4e6c393fb7f5: Waiting

3. 验证

Ubuntu 16.04安装Docker Compose及简单的使用示例

什么是 Docker Compose

Docker Compose 是一个运行多容器 Docker 应用的工具。Compose 通过一个配置文件来配置一个应用的服务,然后通过一个命令创建并启动所有在配置文件中指定的服务。

Docker Compose 适用于许多不同的项目,如:

  • 开发:利用 Compose 命令行工具,我们可以创建一个隔离(而可交互)的环境来承载正在开发中的应用程序。通过使用 Compose 文件,开发者可以记录和配置所有应用程序的服务依赖关系。
  • 自动测试:此用例需求一个测试运行环境。Compose 提供了一种方便的方式来管理测试套件的隔离测试环境。完整的环境在 Compose 文件中定义。

Docker Compose 是在 Fig 的源码上构建的,这个社区项目现在已经没有使用了。

在本教程中,我们将看到如何在 Ubuntn 16.04 上安装 Docker Compose。

安装 Docker

我们需要安装 Docker 来安装 Docker Compose。首先为官方 Docker 仓库添加公钥。

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

接下来,添加 Docker 仓库到 apt 源列表:

$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

更新包数据库,并使用 apt 安装 Docker

$ sudo apt-get update
$ sudo apt install docker-ce

在安装进程结束后,Docker 守护程序应该已经启动并设为开机自动启动。我们可以通过下面的命令来查看它的状态:

$ sudo systemctl status docker
---------------------------------
● docker.service - Docker Application Container Engine
 Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
 Active: active (running) 

安装 Docker Compose

现在可以安装 Docker Compose 了。通过执行以下命令下载当前版本。

# curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

为二进制文件添加执行权限:

# chmod +x /usr/local/bin/docker-compose

检查 Docker Compose 版本:

$ docker-compose -v

输出应该如下:

docker-compose version 1.14.0, build c7bdf9e

测试 Docker Compose

Docker Hub 包含了一个用于演示的 Hello World 镜像,可以用来说明使用 Docker Compose 来运行一个容器所需的配置。

创建并打开一个目录:

$ mkdir hello-world
$ cd hello-world

创建一个新的 YAML 文件:

$ $EDITOR docker-compose.yml

在文件中粘贴如下内容:

unixmen-compose-test:
 image: hello-world

注意: 第一行是容器名称的一部分。

保存并退出。

运行容器

接下来,在 hello-world 目录执行以下命令:

$ sudo docker-compose up

如果一切正常,Compose 输出应该如下:

Pulling unixmen-compose-test (hello-world:latest)...
latest: Pulling from library/hello-world
b04784fba78d: Pull complete
Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f
Status: Downloaded newer image for hello-world:latest
Creating helloworld_unixmen-compose-test_1 ... 
Creating helloworld_unixmen-compose-test_1 ... done
Attaching to helloworld_unixmen-compose-test_1
unixmen-compose-test_1 | 
unixmen-compose-test_1 | Hello from Docker!
unixmen-compose-test_1 | This message shows that your installation appears to be working correctly.
unixmen-compose-test_1 | 
unixmen-compose-test_1 | To generate this message, Docker took the following steps:
unixmen-compose-test_1 | 1. The Docker client contacted the Docker daemon.
unixmen-compose-test_1 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
unixmen-compose-test_1 | 3. The Docker daemon created a new container from that image which runs the
unixmen-compose-test_1 | executable that produces the output you are currently reading.
unixmen-compose-test_1 | 4. The Docker daemon streamed that output to the Docker client, which sent it
unixmen-compose-test_1 | to your terminal.
unixmen-compose-test_1 | 
unixmen-compose-test_1 | To try something more ambitious, you can run an Ubuntu container with:
unixmen-compose-test_1 | $ docker run -it ubuntu bash
unixmen-compose-test_1 | 
unixmen-compose-test_1 | Share images, automate workflows, and more with a free Docker ID:
unixmen-compose-test_1 | https://cloud.docker.com/
unixmen-compose-test_1 | 
unixmen-compose-test_1 | For more examples and ideas, visit:
unixmen-compose-test_1 | https://docs.docker.com/engine/userguide/
unixmen-compose-test_1 | 
helloworld_unixmen-compose-test_1 exited with code 0

Docker 容器只能在命令(LCTT 译注:此处应为容器中的命令)还处于活动状态时运行,因此当测试完成运行时,容器将停止运行。

结论

本文是关于在 Ubuntu 16.04 中安装 Docker Compose 的教程。我们还看到了如何通过一个 YAML 格式的 Compose 文件构建一个简单的项目。

使用Docker Compose部署Django和Vue.js应用

前言

本文主要内容关于使用docker-compose实践部署后端django-rest-framework和前端vue.js应用。记录其中遇到的一些坑以及解决办法。

准备Docker-compose环境

系统:Ubuntu 16.04(阿里云)代码中用户名:test

安装Docker

# install docker
## prepare
echo 'Preparing...'
sudo apt update
sudo apt upgrade -y
sudo apt install -y linux-image-extra-$(uname -r) linux-image-extra-virtual
## docker
echo 'Installing docker...'
sudo apt remove -y docker-ce docker-engine docker.io
wget -qO- http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh
sudo apt autoremove -y

sudo usermod -aG docker ${USER}

## docker Aliyun accelerator
## https://cr.console.aliyun.com/#/accelerator
echo 'Configuring docker registry mirrors...'
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://<your-own>.mirror.aliyuncs.com"]
}
EOF

exists(){
  command -v "$1" >/dev/null 2>&1
}

echo 'Installing docker-compose...'
if ! exists pip; then
    sudo apt install python-pip
fi
sudo python `which pip` install docker-compose

echo 'Restarting docker...'
sudo systemctl daemon-reload
sudo systemctl restart docker

部署

目录结构

.
├── .env // 环境变量
├── docker-compose.yml
├── backend // 放置后台django文件
├── frontend // 放置前端vue编译后代码
└── nginx // nginx相关配置
    ├── backend.conf
    ├── Dockerfile
    └── frontend.conf

具体配置

docker-compose.yml
version: '3'

services:
  web:
    restart: always
    build: ./backend
    expose:
      - "8000"
    volumes:
      - ./backend:/code
    env_file: .env
    links:
      - db
    depends_on:
      - db
    command: ["/code/wait-for-it.sh", "db:3306", "--", "bash","startup.sh"]
  nginx:
    restart: always
    build: ./nginx
    ports:
      - "80:80"
    volumes:
      - ./frontend:/usr/share/nginx/html/frontend:ro
      - ./backend/public:/usr/share/nginx//html/backend/public:ro
    links:
      - web
    depends_on:
      - web
  db:
    restart: always
    image: mysql:latest
    env_file: .env
    volumes:
      - ./data/initsql:/docker-entrypoint-initdb.d
      - ./data/db:/var/lib/mysql
    command: [mysqld, --character-set-server=utf8, --collation-server=utf8_unicode_ci]

第一次使用docker-compose部署,从网上参考了许多例子。但是由于docker-compose个版本的语法改动不小,遇到很多坑:

不同容器共享数据(host主机上的数据)

有些例子使用volumes_from,但是version 3已经删除该设置项更新变化。
官方推荐在根节点(与services同级)下配置volumes,但是没法映射到host主机的文件,有个插件local-persist可以做到,但是不想依赖第三方插件。只能使用麻烦点的写法:在每个service的volume设置项里重复映射host主机的文件

    web:
      volumes:
        - ./backend:/code
    nginx:
      volumes:
        - ./backend/public:/usr/share/nginx//html/backend/public:ro

不同容器互相通信

使用links实现容器间通信。配置需要访问的容器于links配置项下,没什么毛病。

容器启动顺序

实现容器按顺序启动,需要用到depends_on。

但是会有一个问题:depends_on只保证启动顺序,而我们的实际需求是:web容器启动的commands必须等到mysql完全启动,web容器的command才可以执行。因为我们加了restart: always,所以会导致web容器不断重启直到db容器启动完成。

我的解决办法是:给web容器的启动命令加上对mysql服务可用的查询,使用了一个查询脚本wait-for-it:

    command: ["/code/wait-for-it.sh", "db:3306", "--", "bash","startup.sh"]

环境变量

会有多个容器使用相同环境变量的情况,所以都放在.env文件里

    DEBUG=false

    MYSQL_HOST=db
    MYSQL_DATABASE=mydb
    MYSQL_ROOT_PASSWORD=mypass

关于Mysql官方镜像配置

  • 可以定义volume持久化数据库文件:
volumes:
- ./data/db:/var/lib/mysql
  • 如果有初始数据需要导入,可以定义volume映射到/docker-entrypoint-initdb.d:
volumes:
- ./data/initsql:/docker-entrypoint-initdb.d

注意: 该配置只有在/var/lib/mysql/下的mysql目录不存在时才会生效。也就是说,一旦容器启动过一次,之后就在也不会导入/docker-entrypoint-initdb.d里的文件,除非手动清空/var/lib/mysql/(或host主机的./data/db目录)。

关于Nginx容器配置

Dockerfile

    FROM nginx:alpine

    RUN rm /etc/nginx/conf.d/default.conf

    ADD frontend.conf /etc/nginx/conf.d/
    ADD backend.conf /etc/nginx/conf.d/

frontend.conf – vue app build files

    server {
        listen 80 deferred;
        server_name new.bylie.cn;

        root /usr/share/nginx/html/frontend;

        location / {
            try_files $uri $uri/ /index.html =404;
        }

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

backend.conf – django app

    server {
        # use 'listen 80 deferred;' for Linux
        # use 'listen 80 accept_filter=httpready;' for FreeBSD
        listen 80 deferred;
        client_max_body_size 5M;

        # set the correct host(s) for your site
        server_name service.bylie.cn;

        keepalive_timeout 5;

        location /public {
            root /usr/share/nginx/html/backend;
        }

        location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # enable this if and only if you use HTTPS
            # proxy_set_header X-Forwarded-Proto https;
            proxy_set_header Host $http_host;
            # we don't want nginx trying to do something clever with
            # redirects, we set the Host: header above already.
            proxy_redirect off;
            proxy_pass http://web:8000;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

备份数据库到host主机

docker-compose exec db sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --databases ${MYSQL_DATABASE}' > ./backup/database.sql

关于django web容器配置

Dockerfile

    FROM python:3

    ENV PYTHONUNBUFFERED 1
    RUN mkdir /code
    WORKDIR /code
    ADD requirements.txt /tmp/
    RUN pip install -r /tmp/requirements.txt

启动脚本startup.sh

#!/usr/bin/env bash
python manage.py collectstatic --noinput &&
python manage.py migrate &&
gunicorn django_web_app.wsgi:application -w 2 -b :8000

当容器运行起来之后,可能需要导入一些初始数据或者fixtures,我写了一个init的django custom command,手动执行该command:

    docker-compose exec web python manage.py init

使用docker-compose来部署WordPress

很早的时候想维护一个个人Blog,一开始通过 github home page + jekyll,奈何没精力再去把ruby玩溜,自己也不是个擅长改写前端页面的人,无疾而终。今天终于鼓起勇气,买了服务器和域名,部署了wordpress,毕竟wordpress易用易上手,模板也多,也就懒得自己改了。既然本Blog是运行在Docker之上的,那第一篇文章也就来说说这个吧。

部署方式介绍

  • 我的服务器安装的是Arch Linux,自己也是比较喜欢这个极简的Linux发行版。
  • 我使用了docker-compose来做镜像编排工具,nginx,mysql(mairadb),wordpress分别运行于不同的容器。
  • 托上面两个先决条件的福,下面的内容大家根据自己的实际环境,酌情选择。

准备工作

安装Docker

托Arch Linux的福,安装Docker非常简单。

pacman -S docker

安装docker-compose

同样是托Arch的福,安装依旧简单粗暴。

pacman -S docker-compose

准备配置

首先我们需要做的是准备好docker wordpress运行的用户,执行以下命令,添加一个叫wordpress的新用户,将它添加到docker用户组,并为它设置密码

useradd -m -s /bin/zsh wordpress
usermod -a -G docker wordpress
passwd wordpress

紧接着,创建一些目录,保存docker-compose配置文件,存储运行产生的文件,让数据库落地到本机而不是容器,执行以下命令

su - wordpress
cd
mkdir wordpress-compose
touch docker-compose.yml
mkdir -p wordpress-compose/db-data
mkdir -p wordpress-compose/logs/nginx
mkdir -p wordpress-compose/nginx
mkdir -p wordpress-compose/wordpress

这些目录和文件的功能分别如下:

目录或文件 含义

  • wordpress-compose 容器相关根目录
  • wordpress-compose/db-data 数据库数据存储目录
  • wordpress-compose/logs/nginx nginx存储目录
  • wordpress-compose/nginx nginx配置文件
  • wordpress-compose/wordpress wordpress本体,因为安装插件等会改变php文件

接下来我们编写必要的nginx配置文件。在wordpress-compose/nginx下新建wordpress.conf文件,文件中写入下面这些配置,一个很经典的php-fpm的nginx配置文件。

server {
    listen 80;
    server_name www.gsgtzq.com;

    root /var/www/html;
    index index.php;

    access_log /var/log/nginx/wordpress-access.log;
    error_log /var/log/nginx/wordpress-error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        fastcgi_pass wordpress:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

接下来就是docker-compose配置文件的编写了,首先将工作目录切换至刚刚创建的wordpress-compose目录,用自己熟悉的编辑器打开docker-compose.yml文件。

vim docker-compose.yml

先是nginx部分,我使用最新的nginx镜像,暴露80端口给本机,挂载conf.d、log、/var/www/html目录到本机,连接nginx和wordpress容器。

nginx:
        image: nginx:latest
        ports:
                - '80:80'
        volumes:
                - ./nginx:/etc/nginx/conf.d
                - ./logs/nginx:/var/log/nginx
                - ./wordpress:/var/www/html
        links:
                - wordpress
        restart: always

然后是mysql部分,我使用了mairadb的最新镜像,挂载mysql数据存储点到本机,链接mysql和wordpress容器,通过环境变量设置mysql的默认root密码。

mysql:
        image: mariadb:latest
        volumes:
                - ./db-data:/var/lib/mysql
        environment:
                - MYSQL_ROOT_PASSWORD=123345
        restart: always

最后是wordpress本体,我使用wordpress:php7.1-fpm的镜像,挂载/var/www/html目录到本机,链接连接mysql容器和wordpress,并且使用环境变量,指定mysql主机名,表前缀,和库名。

wordpress:
        image: wordpress:php7.1-fpm
        volumes:
                - ./wordpress:/var/www/html
        environment:
                - WORDPRESS_DB_NAME=wpdb
                - WORDPRESS_TABLE_PREFIX=wp_
                - WORDPRESS_DB_HOST=mysql
        links:
                - mysql
        restart: always

到此位置,docker-compose的配置文件全部编写完毕。

启动容器

编排文件已写完,接下来启动容器即可。

docker-compose up -d

当收到三个done以后,编排好的容器就正式启动了,我们现在可以访问本机的IP或域名来访问wordpress了。
我还可以使用下面这些命令来检查容器的运行情况,注意,docker-compose命令只有在刚才写好配置文件的目录下执行才有效果。

命令 含义

  • docker ps -a 查看当前所有运行的docker容器
  • docker-compose logs wordpress 查看wordpress容器的日志
  • docker-compose ps 查看当前编排好的应用的所有容器状态
  • docker-compose top 查看当前编排好的应用中各容器中的进程情况

具体还有一些其他的办法,可以通过查阅docker手册和docker-compose文档来进行使用。

结束语

到此为止,使用docker来运行wordpress已经完成,从开始折腾Docker到现在少说1个半月过去了,也是学习到了非常多的东西,目前而言公司的项目想用起docker来还是有不少难度,我思考了很多使用docker对传统部署和开发带来冲击的问题,例如对开发人员的要求其实高了很多,尤其是在运维这块,基础环境部署等等……但很希望自己能把它用好了,开发受益,运维也受益。

docker和compose一键快速安装脚本

本文介绍快速安装docker和compose的方法。与手动安装相比,一键安装省去了手工输入命令的繁琐步骤且不容易出错。由于国内网络环境原因,连接docker官方服务器异常的慢,这体现为在国内安装docker-engine和拉取镜像非常慢,甚至无法安装和拉取。此脚本通过更换repository和registry mirror解决了此问题。

脚本特性

对于docker-engine的安装,脚本特性如下:

  • 支持centos7,ubuntu,debian系统的安装
  • 支持安装特定版本的docker
  • 根据网络环境测试结果自动选取较快的repository,如国内使用mirrors.ustc.edu.cn,国外使用dockerproject.org
  • 通过测试网络自动为国内设置hub-mirror.c.163.com registry mirror
  • 对于compose的安装,脚本特性如下:

  • 支持所有Linux系统的安装
  • 支持安装特定版本的compose
  • 由于compose托管在amazonaws,国内几乎无法访问,自动设置一个代理下载
  • 使用方法

    1. wget webres.wang/ezhttp.zip
    2. unzip ezhttp.zip
    3. cd ezhttp-master
    4. ./start.sh

    之后会弹出一个菜单,输入2选择Some Useful Tools.
    然后输入17选择安装docker,输入18选择安装compose。

    docker compose文件参考(4) – 变量替换

    配置项可以包含环境变量。compose使用docker-compose运行所在的shell环境的变量值。例如,假设shell包含环境变量EXTERNAL_PORT=8000且配置中引用了此变量:

    1. web:
    2.   build: .
    3.   ports:
    4.     – "${EXTERNAL_PORT}:5000"

    当使用此配置插docker-compose run命令时,compose在shell中查找EXTERNAL_PORT环境变量并使用其值替换此配置文件中对应的占位符。在这个示例中,在创建web容器之前,compose解析端口映射为8000:5000。

    如果环境变量没有设置,compose使用空字符替换。在上面的示例中,如果EXTERNAL_PORT没有设置,端口映射的值为:5000(是一个无效的端口映射,创建容器时会导致错误)。

    可以使用.env文件为环境变量设置默认的值。在shell环境中设置的值会覆盖在.env文件设置的值。

    1. $ unset EXTERNAL_PORT
    2. $ echo "EXTERNAL_PORT=6000" > .env
    3. $ docker-compose up          # EXTERNAL_PORT will be 6000
    4. $ export EXTERNAL_PORT=7000
    5. $ docker-compose up          # EXTERNAL_PORT will be 7000

    $VARIABLE和${VARIABLE}两种写法都支持。如果使用的是2.1文件格式,还可以在一行中设置默认的值:

  • ${VARIABLE:-default}:当VARIABLE没有设置或为空值时使用default值。
  • ${VARIABLE-default} :仅当VARIABLE没有设置时使用default值。
  • 其它的shell风格的扩展功能,如${VARIABLE/foo/bar}不支持。

    可以使用双美元符号来转义美元符号,即阻止compose解析为值。

    1. web:
    2.   build: .
    3.   command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"

    docker compose文件参考(3) – 网络配置

    driver

    指定用于这个网络的驱动。

    默认使用的驱动取决于docker engine的配置,但大多数情况中,单台主机中使用的是bridge,在集群中使用的是overlay。

    1. driver: overlay

    driver_opts

    指定一列键值对选项传递给这个数据卷的驱动。这些选项依赖于驱动。此参数可选。

    1. driver_opts:
    2.     foo: "bar"
    3.     baz: 1

    enable_ipv6

    在这个网络启用IPv6网络支持。从version 2.1文件格式可用。

    ipam

    指定自定义IPAM配置。这个是带几个属性的对象,每个属性都是可选的:

  • driver: 自定义IPAM驱动,而不是default。
  • config: 0个或多个配置块,可以是以下键:
    subnet:表示一个网段的CIDR格式的子网
    ip_range:从指定范围分配容器IP
    gateway:主子网的IPv4或IPv6网关
    aux_addresses:网络驱动程序使用的辅助IPv4或IPv6地址,作为从主机名到IP的映射
  • 一个完整的示例:

    1. ipam:
    2.   driver: default
    3.   config:
    4.     – subnet: 172.28.0.0/16
    5.       ip_range: 172.28.5.0/24
    6.       gateway: 172.28.5.254
    7.       aux_addresses:
    8.         host1: 172.28.1.5
    9.         host2: 172.28.1.6
    10.         host3: 172.28.1.7

    docker compose文件参考(2) – 数据卷配置

    driver

    指定这个数据卷使用的数据卷驱动。默认为local。如果驱动不可用,docker engine将会返回一个错误。

    1. driver: foobar

    driver_opts

    指定一列键值对选项传递给这个数据卷的驱动。这些选项依赖于驱动。此参数可选。

    1. driver_opts:
    2.    foo: "bar"
    3.    baz: 1

    external

    如果设置为true,表示这个数据卷已经在compose外部创建好了。docker-compose up将不会尝试创建它。

    external不能与其它的数据卷配置关键词(driver, driver_opts)一起使用。

    在下面的示例中,compose不会尝试创建名为[projectname]_data的数据卷,而是仅仅查找一个称为data存在的数据卷并挂载它到db服务的容器。

    1. version: ‘2’
    2.  
    3. services:
    4.   db:
    5.     image: postgres
    6.     volumes:
    7.       – data:/var/lib/postgresql/data
    8.  
    9. volumes:
    10.   data:
    11.     external: true

    也可以指定在compose文件内引用的数据卷名称:

    1. volumes:
    2.   data:
    3.     external:
    4.       name: actual-name-of-volume

    docker compose文件参考(1) – 服务配置

    build

    这个配置选项应用在构建镜像时。

    build可以指定包含构建上下文路径的字符串,或者是context指定一个路径和可选的dockerfile和args。

    1. build: ./dir
    2.  
    3. build:
    4.   context: ./dir
    5.   dockerfile: Dockerfile-alternate
    6.   args:
    7.     buildno: 1

    如果指定了image和build,那么compose以image中指定的名称命名构建的镜像,如:

    1. build: ./dir
    2. image: webapp:tag

    compose将由./dir构建的镜像命名为webapp,tag为tag。

    注意:在version 1文件格式中,build有两点不同的地方:
    1.只允许build: .一种格式,不允许对象格式。
    2.不允许build与image一起使用。

    context

    context可用于verion 2文件格式或以上版本,version 1中只用build。

    指定一个包含Dockerfile的目录路径,或git存储库url。

    当指定了一个相对路径,就解析为相对compose文件所在的目录。这个目录也是发送到docker daemon的构建上下文。

    1. build:
    2.   context: ./dir

    dockerfile

    替代的Dockerfile

    compose使用另一个dockerfile文件构建镜像。必须指定一个context构建路径。

    注意:在verions 1文件格式中,dockerfile有两点不同:
    1.它出现在build的同级,而不是作为它的子选项:

    1. build: .
    2. dockerfile: Dockerfile-alternate

    2.不允许dockerfile与image一起使用。

    args

    此选项只支持version 2文件格式和之上版本。

    增加build参数,这些参数是只在构建期间访问的环境变量。

    首先,在Dockerfile中指定参数:

    1. ARG buildno
    2. ARG password
    3.  
    4. RUN echo "Build number: $buildno"
    5. RUN script-requiring-password.sh "$password"

    然后在build下面指定参数。可以传递映射或列表:

    1. build:
    2.   context: .
    3.   args:
    4.     buildno: 1
    5.     password: secret
    6.  
    7. build:
    8.   context: .
    9.   args:
    10.     – buildno=1
    11.     – password=secret

    compose文件中可以只指定参数名不设置值,在这种情况下参数的值就是compose运行所在shell的环境变量值。

    1. args:
    2.   – buildno
    3.   – password

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

    command

    覆盖默认的命令。

    1. command: bundle exec thin -p 3000

    命令也可以是一个列表,与dockerfile中的列表类似:

    1. command: [bundle, exec, thin, -p, 3000]

    container_name

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

    1. container_name: my-web-container

    因为docker容器名称必须是唯一的,所以如果指定了一个自定义的名称,不能扩展一个服务超过1个容器。

    depends_on

    指定服务之间的依赖关系,有两种效果:

  • docker-compose up将以依赖顺序启动服务。在下面的示例中,db和redis在web之前启动。
  • docker-compose up SERVICE将自动包括SERVICE的依赖。在下面的示例中,docker-compose up web也会创建和启动db和redis。
  • 简单的示例:

    1. version: ‘2’
    2. services:
    3.   web:
    4.     build: .
    5.     depends_on:
    6.       – db
    7.       – redis
    8.   redis:
    9.     image: redis
    10.   db:
    11.     image: postgres

    注意:depends_on不会等到db和redis状态为“ready”才启动web – 它只等到它们已经开始启动。如果需要等到一个服务变为ready,查看Controlling startup order

    dns

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

    1. dns: 8.8.8.8
    2. dns:
    3.   – 8.8.8.8
    4.   – 9.9.9.9

    dns_search

    自定义search域名。可以是单个值或列表。

    1. dns_search: example.com
    2. dns_search:
    3.   – dc1.example.com
    4.   – dc2.example.com

    tmpfs

    需要version 2文件格式或以上版本。

    在容器内部挂载一个临时文件系统。可以是单个值或列表。

    tmpfs: /run
    tmpfs:
    – /run
    – /tmp

    entrypoint

    覆盖默认的entrypoint。

    1. entrypoint: /code/entrypoint.sh

    entrypoint也可以是一个列表:

    1. entrypoint:
    2.     – php
    3.     – -d
    4.     – zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    5.     – -d
    6.     – memory_limit=-1
    7.     – vendor/bin/phpunit

    注意:设置entrypoint将会覆盖默认使用ENTRYPOINT Dockerfile指令设置服务镜像的entrypoint,也会清除这个镜像的任何默认命令 – 意味着如果Dockerfile中指定的任何CMD指定将会忽略。

    env_file

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

    如果使用docker-compose -f FILE指定了一个compose文件,那么在env_file的路径就是相对于那个文件所在的目录。

    在environment关键词指定的环境变量将会覆盖env_file设置的值。

    1. env_file: .env
    2.  
    3. env_file:
    4.   – ./common.env
    5.   – ./apps/web.env
    6.   – /opt/secrets.env

    env文件中每行的格式为VAR=VAL。以#开头的行将忽略,也包括空行。

    1. # Set Rails/Rack environment
    2. RACK_ENV=development

    注意:如果服务指定了一个build选项,定义在env文件中的变量在构建期间不可用。使用build的子选项来定义在构建期间使用的环境变量。

    VAL的值按原样使用,不再不修改。 例如,如果值由引号括起来(通常是shell变量的情况),引号将包含在传递给Compose的值中。

    environment

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

    1. environment:
    2.   RACK_ENV: development
    3.   SHOW: ‘true’
    4.   SESSION_SECRET:
    5.  
    6. environment:
    7.   – RACK_ENV=development
    8.   – SHOW=true
    9.   – SESSION_SECRET

    expose

    暴露只在链接服务之间可用的端口。只能指定内部使用的端口。

    1. expose:
    2.  – "3000"
    3.  – "8000"

    extends

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

    extends可以与service相关的配置项一起使用。extends的值必须是一个字典,其中service是必须的以及一个可选的file选项。

    1. extends:
    2.   file: common.yml
    3.   service: webapp

    service指定的是扩展服务到当前服务的名称。例如web或databases。file指定的是定义有那个service的compose文件。

    如果不指定file选项,compose则在当前文件查找service的配置。file值可以是一个绝对的或相对的路径。如果指定一个相对的路径,这个路径就是相对于当前文件所在目录的路径。

    可以扩展一个本身扩展有另一个的服务。

    external_links

    链接那些在docker-compose.yml外部启动的容器或甚至是在compose外部的,特别是那么提供共享或通用服务的容器。

    external_links在指定容器名称和链接别名(CONTAINER:ALIAS)时遵循类似于链接的语义。

    1. external_links:
    2.  – redis_1
    3.  – project_db_1:mysql
    4.  – project_db_1:postgresql

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

    extra_hosts

    添加主机名映射。与docker客户端的–add-host参数作用一样。

    1. extra_hosts:
    2.  – "somehost:162.242.195.82"
    3.  – "otherhost:50.31.209.229"

    这些定义的ip地址和主机条目将在容器内部的/etc/hosts文件里,如:

    1. 162.242.195.82  somehost
    2. 50.31.209.229   otherhost

    image

    指定从其启动容器的镜像。可以是repository/tag或部分镜像ID。

    1. image: redis
    2. image: ubuntu:14.04
    3. image: tutum/influxdb
    4. image: example-registry.com:4000/postgresql
    5. image: a4bc65fd

    如果镜像不存在,compose尝试拉取它,除非也指定了build,在这种情况下它使用指定的选项来构建镜像并使用指定的tag来作标记。

    注意:在version 1文件格式中,不允许build和image一起使用。

    links

    链接到另一个服务的容器。可以指定服务名称和链接别名(SERVICE:ALIAS),或只是服务名称。

    1. web:
    2.   links:
    3.    – db
    4.    – db:database
    5.    – redis

    可以使用与别名一样的主机名访问链接服务的容器,或者如果没有指定别名就使用服务名称。

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

    注意:如果定义了links和网络,为了能够通信,链接的服务之间必须至少在一个相同的网络。

    logging

    version 2文件格式或更高版本。在version 1中,使用是的log_driver和log_opt。

    服务的日志配置。

    logging:
    driver: syslog
    options:
    syslog-address: “tcp://192.168.0.42:123”

    driver名称指定一个服务容器的日志驱动,相当于docker run的–log-driver。
    默认的值是json-file。

    1. driver: "json-file"
    2. driver: "syslog"
    3. driver: "none"

    使用options关键词指定日志驱动的日志选项,就像docker run的log-opt选项。

    日志选项是键值对。一个syslog选项的示例:

    1. driver: "syslog"
    2. options:
    3.   syslog-address: "tcp://192.168.0.42:123"

    network_mode

    要求version 2文件格式和之后版本。version 1使用net。

    网络模式。与docker客户端的–net参数一样,加上一个特别的格式service:[service name]。

    1. network_mode: "bridge"
    2. network_mode: "host"
    3. network_mode: "none"
    4. network_mode: "service:[service name]"
    5. network_mode: "container:[container name/id]"

    networks

    要求version 2文件格式和之后版本。version 1使用net。

    要加入的网络,在顶层networks关键词之下引用网络。

    1. services:
    2.   some-service:
    3.     networks:
    4.      – some-network
    5.      – other-network

    aliases

    在网络中服务的别名(替代主机名)。在同一网络的其它容器可以使用服务名称或这个别名来连接服务容器的其中一个。

    因为别名作用域是网络内,所以同一服务在不同的网络可以有不同的别名。

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

    一般的格式如下:

    1. services:
    2.   some-service:
    3.     networks:
    4.       some-network:
    5.         aliases:
    6.          – alias1
    7.          – alias3
    8.       other-network:
    9.         aliases:
    10.          – alias2

    在下面的示例中,配置了三个服务(web,worker和db)和两个网络(new和legay)。在net网络上可以使用db主机名或database访问db服务,在legacy网络上可以使用db或mysql访问db服务。

    1. version: ‘2’
    2.  
    3. services:
    4.   web:
    5.     build: ./web
    6.     networks:
    7.       – new
    8.  
    9.   worker:
    10.     build: ./worker
    11.     networks:
    12.     – legacy
    13.  
    14.   db:
    15.     image: mysql
    16.     networks:
    17.       new:
    18.         aliases:
    19.           – database
    20.       legacy:
    21.         aliases:
    22.           – mysql
    23.  
    24. networks:
    25.   new:
    26.   legacy:

    ipv4_address, ipv6_address

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

    顶层networks区域的相关网络配置必须有一个指定有子网和网关覆盖每个静态地址的配置的ipadm块。如果要使用IPv6地址,必须设置com.docker.network.enable_ipv6驱动选项为true。
    示例:

    1. version: ‘2’
    2.  
    3. services:
    4.   app:
    5.     image: busybox
    6.     command: ifconfig
    7.     networks:
    8.       app_net:
    9.         ipv4_address: 172.16.238.10
    10.         ipv6_address: 2001:3984:3989::10
    11.  
    12. networks:
    13.   app_net:
    14.     driver: bridge
    15.     driver_opts:
    16.       com.docker.network.enable_ipv6: "true"
    17.     ipam:
    18.       driver: default
    19.       config:
    20.       – subnet: 172.16.238.0/24
    21.         gateway: 172.16.238.1
    22.       – subnet: 2001:3984:3989::/64
    23.         gateway: 2001:3984:3989::1

    ports

    暴露端口。可以指定两个端口(HOST:CONTAINER),或只指定一个容器端口(将选择一个随机的主机端口)。

    1. ports:
    2.  – "3000"
    3.  – "3000-3005"
    4.  – "8000:8000"
    5.  – "9090-9091:8080-8081"
    6.  – "49100:22"
    7.  – "127.0.0.1:8001:8001"
    8.  – "127.0.0.1:5000-5010:5000-5010"

    ulimits

    覆盖容器默认的ulimits。可以指定单个限制或soft/hard限制。

    1. ulimits:
    2.   nproc: 65535
    3.   nofile:
    4.     soft: 20000
    5.     hard: 40000

    volumes, volume_driver

    挂载路径或命名数据卷,可选地指定主机的路径(HOST:CONTAINER),或权限模式(HOST:CONTAINER:ro)。对于version 2文件,命名数据卷必须在顶层volumes关键词中指定。当使用version 1时,当命名数据卷不存在时docker engine将会自动创建。

    可以挂载主机的一个相对路径,此路径相对于正在使用的compose文件所在的目录。相对的路径以.或..开头。

    1. volumes:
    2.   # Just specify a path and let the Engine create a volume
    3.   – /var/lib/mysql
    4.  
    5.   # Specify an absolute path mapping
    6.   – /opt/data:/var/lib/mysql
    7.  
    8.   # Path on the host, relative to the Compose file
    9.   – ./cache:/tmp/cache
    10.  
    11.   # User-relative path
    12.   – ~/configs:/etc/configs/:ro
    13.  
    14.   # Named volume
    15.   – datavolume:/var/lib/mysql

    如果不使用主机路径,可能要指定一个volume_driver。

    1. volume_driver: mydriver

    注意,对于version 2文件,这个驱动不会应用到命名数据卷(当声明数据卷时应该使用driver选项)。对于version 1,命名数据卷和容器数据卷使用这个指定的驱动。

    volumes_from

    挂载从另一个服务或容器的所有数据卷,可选地指定只读权限(ro)或读写(rw)。如果没有指定权限级别,将使用读写(rw)权限。

    1. volumes_from:
    2.  – service_name
    3.  – service_name:ro
    4.  – container:container_name
    5.  – container: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

    1. cpu_shares: 73
    2. cpu_quota: 50000
    3. cpuset: 0,1
    4.  
    5. user: postgresql
    6. working_dir: /code
    7.  
    8. domainname: foo.com
    9. hostname: foo
    10. ipc: host
    11. mac_address: 02:42:ac:11:65:43
    12.  
    13. mem_limit: 1000000000
    14. memswap_limit: 2000000000
    15. privileged: true
    16.  
    17. oom_score_adj: 500
    18.  
    19. restart: always
    20.  
    21. read_only: true
    22. shm_size: 64M
    23. stdin_open: true
    24. tty: true

    在生产环境使用docker compose

    当在compose定义你的app用于开发环境时,也可以使用这个配置来在不同的环境,如CI,临时和生产环境运行应用程序。

    更改compose文件适用于生产环境

    在把compose部署到生产环境之前,虽然更改你的app配置,这些更改包括:

  • 删除应用程序代码的挂载,以使代码留在容器内,保证无法从外部更改。
  • 绑定不同的主机端口
  • 设置不同的环境变量(如降低日志的详细程序或启用邮件发送)
  • 指定一个重启策略(如restart: always)来避免宕机时间
  • 增加额外的服务(如,日志聚合器)
  • 以上这么多的更改,可以定义一个额外的compose文件,称为production.yml,定义了适合生产环境的配置。这个文件只需要包含你想要对原始文件的更改部分。可以通过原始docker-compose.yml应用额外的Compose文件来创建新配置。

    一旦完成了第二个配置文件的编写,使用-f选项告诉compose使用它:

    1. docker-compose -f docker-compose.yml -f production.yml up -d

    部署更改

    当对你的app代码更改后,需要重建镜像和容器。要重新部署web服务,使用:

    1. $ docker-compose build web
    2. $ docker-compose up –no-deps -d web

    第一个命令重建web的镜像然后停止,销毁和重建web服务。–no-deps选项阻止compose重新创建web信赖的服务。