Docker Compose是一个定义和管理多容器的工具,也是一种容器编排工具,前身是Pig,使用Python语言编写。使用Docker Compose配置文件描述多个容器应用的架构,比如使用什么镜像、数据卷、网络、映射端口等;然后一条命令管理所有服务,比如启动、停止、重启等。


Docker Compose的安装:

1)下载二进制文件

wget https://github.com/docker/compose/releases/download/1.13.0/docker-compose-`uname -s`-`uname -m`

2)添加可执行权限

mv docker-compose-Linux-x86_64 /usr/bin/docker-compose

chmod +x /usr/bin/docker-compose 

3)验证安装结果

[root@centos7 ~]# docker-compose --version

docker-compose version 1.13.0, build 1719ceb


Docker Compose的使用:

docker compose 将所管理的容器分为三层,分别是工程(project),服务以及容器。docker compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程(默认为docker-compose.yml所在目录的名称)。一个工程可包含多个服务,每个服务中定义了容器运行的镜像,参数和依赖,一个服务可包括多个容器实例

Docker Compose的操作步骤:

  • 使用 dockerfile 定义应用程序环境,以便在任何地方重现该环境

  • 在docker-compose.yml文件中定义组成应用程序的服务,以便各个服务在一个隔离的环境中一起运行

  • 运行 docker-compose up 命令,启动并运行整个应用程序

前面已经介绍过dockerfile,所以这里介绍一下Docker Compose的配置文件。Docker Compose使用YAML作为其配置文件格式,在docker-compose.yml文件中定义了容器的镜像、参数、端口、启动顺序等。YAML是一种标记语言很直观的数据序列化格式,可读性高,类似于XML数据描述语言,但语法比XML简单很多。YAML数据结构通过缩进来表示,连续的项目通过减号来表示,键值对用冒号分隔,数组用中括号括起来,hash用花括号括起来。

YAML文件格式注意事项:

  • 不支持制表符tab键缩进,需要使用空格缩进;

  • 通常开头缩进2个空格;

  • 字符后缩进1个空格,如冒号、逗号、横杠;

  • 用#进行注释;

  • 如果包含特殊字符用单引号引起来;

  • 布尔值(true、false、yes、no、on、off)必须用引号括起来,这样分析器会将它们解释为字符串;


Compose配置文件常用参数:

build:构建镜像上下文路径

dockerfile:指定dockerfile文件名

image:来自镜像

args:构建参数,在dockerfile中指定的参数

command:覆盖默认命令

container_name:自定义容器名称。如果自定义名称,则无法将服务scale到1容器之外

deploy:指定与部署和运行相关的配置。限版本3

depends_on:服务之间的依赖,控制服务启动顺序,正常是按顺序启动服务

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

entrypoint:覆盖entrypoint

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

environment:添加环境变量,可以是数组或字典,布尔值用引号括起来

expose:声明容器服务端口

links:连接到另一个容器

external_links:连接Compose之外的容器

extra_hosts:添加主机名映射,与--add-host相同

logging:记录该服务的日志,与--log-driver相同

network_mode:网络模式,与--net相同

networks:要加入的网络

pid:将PID模式设置主机PID模式,与宿主机共享PID地址空间,如pid: "host"

ports:暴露端口,与-p相同,但端口不低于60

sysctls:在容器内设置内核参数,可以是数组或字典

ulimits:覆盖容器的默认ulimits

volumes:挂载一个目录或一个已存在的数据卷容器到容器

restart:默认no,可选参数always|on-failure|unless-stopped

hostname:主机名

working_dir:工作目录


docker-compose.yml示例:

[root@centos7 compose_proj01]# cat docker-compose.yml 
version: '3'
services:
  nginx:
    hostname: nginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - "80:80"
    links:
      - "tomcat01:tomcat01"
      - "tomcat02:tomcat02"
    volumes:
      - ./webapps:/usr/local/nginx/html
    depends_on:
      - tomcat01
      - tomcat02
  tomcat01:
    hostname: tomcat01
    build: ./tomcat
    volumes:
      - ./webapps/tomcat01:/usr/local/tomcat/webapps
  tomcat02:
    hostname: tomcat02
    build: ./tomcat
    volumes:
      - ./webapps/tomcat02:/usr/local/tomcat/webapps


Docker Compose常用选项:

用法:docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]

-f, --file FILE:指定Compose配置文件,默认docker-compose.yml

-p, --project-name NAME:指定项目名称,默认目录名

--verbose:显示更多的输出

-v, --version:显示docker compose版本

-H, --host HOST:指定守护socket连接到指定的主机

--project-directory PATH:指定一个可选的工作目录,默认为当前compose文件所在目录


Docker Compose常用命令:

build:重新构建服务

    用法:build [options] [--build-arg key=val...] [SERVICE...]

        --no-cache:不适用缓存构建镜像

        --build-arg key=val:设置构建时的变量

config:验证和查看Compose文件

    用法:config [options]

        -q, --quite:只验证不打印

        --services:只打印服务名称,每行一个

        --volumes:打印数据卷名称,每行一个

exec:在运行的容器里执行命令

    用法:exec [options] SERVICE COMMAND [ARGS...]

        -d:在后台运行命令

        --privileged:给这个进程赋予特权权限

        --user USER:作为该用户运行该命令

        -T:禁用分配伪终端,默认分配一个终端

        --index=index:多个容器时的索引数字,默认为1

port:打印绑定的开放端口

    用法:port [options] SERVICE PRIVATE_PORT

        --protocol=proto:tcp或udp协议,默认为tcp

        --index=index:多个容器时的索引数字,默认为1

ps:列出容器

    用法:ps [options] [SERVICE...]

        -q:只显示ID

rm:删除停止的服务容器

    用法:rm [options] [SERVICE...]

        -f, --force:强制删除

        -s, --stop:删除容器时如果需要先停止容器

        -v:删除与容器相关的任何匿名卷

scale:指定一个服务启动容器数量

    用法:scale [options] [SERVICE=NUM...]

        -t, --timeout TIMEOUT:指定一个停止超时时间,单位为秒,默认为10秒

up:创建和启动容器

    用法:up [options] [--scale SERVICE=NUM...] [SERVICE...]

        -d:在后台运行容器

        --no-deps:不启动连接服务

        --force-recreate:强制重建容器,即使它们的配置和镜像未发生任何修改

        --no-recreate:如果容器存在,不重建它们

        --no-build:不构建镜像,即使它丢失

        --build:启动容器前先构建镜像

        --scale SERVICE=NUM:指定一个服务(容器)的启动数量

stop:停止服务

    用法:stop [options] [SERVICE...]

        -t, --timeout TIMEOUT:指定停止服务的超时时间,单位为秒,默认值为10

start:启动服务

    用法:start [SERVICE...]

restart:重启服务

    用法:restart [options] [SERVICE...]

top:显示容器运行的进程

    用法:top [SERVICE...]

logs:显示容器的输出

    用法:logs [options] [SERVICE...]

        -f, --follow:实时输出日志

        -t, --timestamps:显示时间戳

        --tail="all":从日志末端显示行数

down:停止容器和删除容器、网络、数据卷和镜像

    用法:down [options]

        --rmi type:移除镜像,type能接收的值为:all,local。如果为all,则移除该服务用到的所有镜像;如果为local,则仅移除那些在image字段没有设置自定义标签的镜像。

        -v, --volumes:移除在volume区域定义的且链接到容器上的有命名的和匿名的数据卷

        --remove-orphans:移除在compose配置文件中为定义的服务容器


示例1:使用Docker compose部署nginx+tomcat环境

说明:目的是使用docker-compose部署nginx和tomcat的环境,使用nginx反向代理tomcat展示内容。

1)演示的文件目录结构如下

[root@centos7 compose_proj01]# tree
.
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── nginx.conf
├── tomcat
│   ├── apache-tomcat-8.5.38.tar.gz
│   ├── Dockerfile
│   └── jdk-8u162-linux-x64.tar.gz
└── webapps
    ├── hello.html
    ├── timg.jpg
    ├── tomcat01
    │   └── ROOT
    │       └── index.jsp
    └── tomcat02
        └── ROOT
            └── index.jsp
7 directories, 10 files

2)nginx目录的相关设置

注:nginx的Dockerfile使用的是前面dockerfile里记录的,所以不在赘述,这里补充一下nginx里的相关配置。

......
    upstream composeproj01 {
        server tomcat01:8080;
        server tomcat02:8080;
    }
    server {
        listen 80;
        server_name localhost;
        server_tokens off;
        location / {
            proxy_pass http://composeproj01;
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header SSL_CERT $ssl_client_cert;
            proxy_set_header X-Forwarded-For $remote_addr;
        }
        location ~ \.(html|css|jpg|png|gif)$ {
            root /usr/local/nginx/html;
        }
    }
......

3)tomcat目录的相关配置

注:tomcat的Dockerfile是用的也是前面的java镜像的构建文件,也不再过多介绍。

4)webapps的相关配置

[root@centos7 compose_proj01]# ll webapps/
total 40
-rw-r--r-- 1 root root    13 Apr 17 09:43 hello.html
-rw-r--r-- 1 root root 26591 Apr 17 09:29 timg.jpg
drwxr-xr-x 3 root root  4096 Apr 17 09:30 tomcat01
drwxr-xr-x 3 root root  4096 Apr 17 09:31 tomcat02
[root@centos7 compose_proj01]# tree webapps/
webapps/
├── hello.html
├── timg.jpg
├── tomcat01
│   └── ROOT
│       └── index.jsp
└── tomcat02
    └── ROOT
        └── index.jsp
4 directories, 4 files
[root@centos7 compose_proj01]# cat webapps/tomcat01/ROOT/index.jsp 
Display on tomcat01.
[root@centos7 compose_proj01]# cat webapps/tomcat02/ROOT/index.jsp 
Display on tomcat02.

5)docker-compose.yml配置

[root@centos7 compose_proj01]# cat docker-compose.yml 
version: '3'
services:
  nginx:
    hostname: nginx
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - "80:80"
    links:
      - "tomcat01:tomcat01"
      - "tomcat02:tomcat02"
    volumes:
      - ./webapps:/usr/local/nginx/html
    depends_on:
      - tomcat01
      - tomcat02
  tomcat01:
    hostname: tomcat01
    build: ./tomcat
    volumes:
      - ./webapps/tomcat01:/usr/local/tomcat/webapps
  tomcat02:
    hostname: tomcat02
    build: ./tomcat
    volumes:
      - ./webapps/tomcat02:/usr/local/tomcat/webapps

6)使用Docker Compose进行构建

[root@centos7 compose_proj01]# docker-compose up -d

<过程略>

7)验证结果

0001.png

0002.png

0004.png

0003.png

结论:通过docker-compose.yml成功部署了nginx和tomcat的环境,将webapps目录分别挂载到nginx和tomcat的工作目录中,实现动态内容通过tomcat展现,静态内容通过nginx展现。而这种动静分离一般都需要分别将服务部署在不同的机器上,使用docker compose很方便的就一步完成了。



示例2:使用Docker compose部署LNMP环境搭建wordpress

1)演示的文件目录结构如下:

[root@centos7 wordpress]# tree
.
├── dbdata
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── nginx.conf
├── php
│   ├── Dockerfile
│   └── php-5.6.10.tar.gz
└── webcontent
    ├── nginxconf
    │   └── wordpress.conf
    └── wordpress

注:dbdata用来存放mysql的数据文件,以防容器挂掉导致数据丢失。webcontent目录用来存放网站内容,包含nginxconf目录用来存放conf.d中的nginx配置文件,里面有wordpress.conf的配置文件,wordpress目录用来存放网站内容(从网上下载的wordpress压缩包,解压到此处即可),这里就不展开里面的内容了。

2)nginx目录的相关配置

nginx的Dockerfile之前已经讲过,这里不再贴出来。而nginx.conf文件也仅仅跟默认模板保持一致,这里跟示例1不同,就不将wordpress的配置写到nginx.conf中,但是需要添加如下配置:

include /usr/local/nginx/conf.d/*.conf;  

这样的目的在于,通过docker-compose.yml将webcontent/nginxconf目录挂载到nginx容器中的/usr/local/nginx/conf.d目录,只需将写好的*.conf存放到webcontent/nginxconf中,这样nginx容器就可以应用该配置,相较上一个配置更灵活一些。

3)php目录的相关配置

PHP的Dockerfile,内容如下:

[root@centos7 wordpress]# cat php/Dockerfile 
FROM centos:latest
MAINTAINER "jerry12356@126.com"
ENV PHP_BASEDIR=/usr/local/php PVERSION=5.6.10 TIME_ZONE="Asia/Shanghai"
RUN rm -f /etc/yum.repo.d/*
ADD http://mirrors.aliyun.com/repo/Centos-6.repo /etc/yum.repo.d/
RUN rpm -Uvh http://mirrors.ustc.edu.cn/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN yum -y install gcc gcc-c++ make gd-devel openssl-devel libxml2 libxml2-devel bzip2 bzip2-devel \
    libjpeg-turbo libjpeg-turbo-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel  \
    libcurl libcurl-devel openssl openssl-devel glibc glibc-devel autoconf libjpeg libjpeg-devel   \
    libiconv libiconv-devel bison bison-devel readline-devel libicu-devel libedit-devel \
    sqlite-devel jemalloc jemalloc-devel libxslt-devel libmcrypt libmcrypt-devel mhash mhash-devel \
    mcrypt pcre pcre-devel curl curl-devel openldap openldap-devel
RUN groupadd www && useradd -g www -s /sbin/nologin www
ADD php-5.6.10.tar.gz /tmp/
RUN cd /tmp/php-${PVERSION} && ./configure --prefix=/usr/local/php \
    --with-config-file-path=/usr/local/php/etc \
    --with-fpm-user=www  \
    --with-fpm-group=www \
    --with-mysql=mysqlnd \
    --with-mysqli=mysqlnd \
    --with-pdo-mysql=mysqlnd \
    --with-gd \
    --with-iconv \
    --with-mcrypt \
    --with-mhash \
    --with-openssl \
    --with-curl \
    --with-zlib \
    --with-bz2 \
    --with-freetype-dir \
    --with-jpeg-dir \
    --with-png-dir \
    --with-xsl \
    --with-pcre-dir \
    --with-gettext \
    --with-xmlrpc \
    --enable-bcmath \
    --enable-soap \
    --enable-mbregex \
    --enable-pcntl \
    --enable-opcache \
    --enable-fpm \
    --enable-shmop \
    --enable-xml \
    --enable-sockets \
    --enable-zip \
    --enable-mbstring \
    --enable-inline-optimization \
    --disable-debug \
    --disable-rpath \
    --disable-ipv6 \
    && make && make install \
    && echo -e 'PATH=$PATH:/usr/local/php/bin:/usr/local/php/sbin' >> /etc/profile && source /etc/profile \
    && cd /usr/local/php/etc/ && cp php-fpm.conf.default php-fpm.conf \
    && sed -i 's/127.0.0.1/0.0.0.0/g' /usr/local/php/etc/php-fpm.conf \
    && cp /tmp/php-${PVERSION}/php.ini-production /usr/local/php/etc/php.ini \
    && chown -R www:www /usr/local/php \
    && cp /tmp/php-${PVERSION}/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm \ 
    && chmod 755 /etc/init.d/php-fpm && chkconfig --add php-fpm && chkconfig php-fpm on \
    && echo "${TIME_ZONE}" > /etc/timezone && ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime \
    && yum clean all && rm -rf /tmp/* 
CMD /etc/init.d/php-fpm start && tail -F /var/log/messages
EXPOSE 9000

4)webcontent中wordpress.conf的内容

[root@centos7 wordpress]# cat webcontent/nginxconf/wordpress.conf 
server {
    listen 80;
    server_name localhost;
    server_tokens off;
    
    access_log logs/access.log main;
    error_log  logs/error.log;
    root /usr/local/nginx/html;
    index index.php;
    location ~ .*\.(php|php5)?$ {
        fastcgi_pass php-cgi:9000;
        include /usr/local/nginx/conf/fastcgi.conf;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }
}

5)docker-compose.yml的相关配置

[root@centos7 wordpress]# cat docker-compose.yml 
version: '3'
services: 
  mysqldb:
    hostname: mysqldb
    image: mysql:5.6
    volumes: 
      - ./dbdata:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
      
  php-cgi:
    hostname: php-cgi
    build:
      context: ./php
      dockerfile: Dockerfile
    links:
      - "mysqldb:mysqldb"
    depends_on:
      - mysqldb
    volumes:
      - ./webcontent/wordpress:/usr/local/nginx/html
      
  nginx:
    hostname: nginx
    build: ./nginx
    ports: 
      - "80:80"
    links:
      - "php-cgi:php-cgi"
      - "mysqldb:mysqldb"
    volumes:
      - ./webcontent/nginxconf:/usr/local/nginx/conf.d
      - ./webcontent/wordpress:/usr/local/nginx/html
    depends_on:
      - mysqldb
      - php-cgi

6)使用Docker Compose进行构建

[root@centos7 wordpress]# docker-compose up -d
Creating network "wordpress_default" with the default driver
Creating wordpress_mysqldb_1 ... 
Creating wordpress_mysqldb_1 ... done
Creating wordpress_php-cgi_1 ... 
Creating wordpress_php-cgi_1 ... done
Creating wordpress_nginx_1 ... 
Creating wordpress_nginx_1 ... done
[root@centos7 wordpress]# docker-compose ps
       Name                      Command               State         Ports        
---------------------------------------------------------------------------------
wordpress_mysqldb_1   docker-entrypoint.sh mysqld      Up      3306/tcp           
wordpress_nginx_1     ./sbin/nginx -g daemon off;      Up      0.0.0.0:80->80/tcp 
wordpress_php-cgi_1   /bin/sh -c /etc/init.d/php ...   Up      9000/tcp

7)验证部署结果

001.png

这里因为已经在wordpress中的wp-config.php配置了mysql数据库的账号密码,所以这里只需要设置一下标题和管理员信息即可。

002.png

使用刚刚创建的用户名密码登录

003.png

结论:通过docker-compose.yml成功部署了LNMP环境,将宿主机上的nginxconf目录挂载到nginx容器中的/usr/local/nginx/conf.d中,这样添加nginx配置文件很方便(不过也需要在docker-compose构建前写好),然后将webcontent挂载到/usr/local/nginx/html中,这样对.php文件的访问都转发给php-cgi容器,最后通过nginx来展现。虽然没有使用官方的wordpress镜像,但是这样做容器间的耦合性很小,而且还可以增加PHP节点,处理更多的请求,数据也能持久化存储,架构更清晰了。