Docker 学习笔记 - Day3

  LeungJZ

Docker 学习笔记 - Day3

docker-compose

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

Docker-compose 是一个定义和运行多容器 Docker 程序的工具。在 compose 中,可以用 YAML 文件来配置程序的服务,然后使用简单的命令即可从配置中创建并启动所有服务。

一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose,不再需要使用 shell 脚本来启动容器。在配置文件中,所有的容器通过 services 来定义,然后使用 docker-compose 脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器。

安装 compose

Linux:

# 下载最新的 docker-compose 
sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 给予下载的 docker-compose 执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 测试是否可用
docker-compose --version
docker-compose version 1.15.0, build e12f3b9

其他操作系统可以 查看这里

配置 docker-compose.yml

整个配置文件应该包含 version 、services 、 networks 三大部分,其中最关键是 services 和 networks 两部分。

version

下表显示了 compose 文件版本支持特定的 docker 版本。

Compose file format Docker Engine release
3.3 17.06.0+
3.2 17.04.0+
3.1 1.13.1+
3.0 1.13.0+
2.3 17.06.0+
2.2 1.13.0+
2.1 1.12.0+
2.0 1.10.0+
1.0 1.9.1.+

services

在 services 标签下的标签是指该服务的名称,为用户自定义。

  1. image

指定服务的镜像名称或者镜像ID ,若本地不存在,则 compose 将会尝试拉取该镜像。

用法:

image: ubuntu
image: nginx:1.13
image: containerID
  1. build

服务即可基于某个镜像 image ,亦可基于一个 Dockerfile 文件。在使用命令 docker-compose up 构建任务时,将会自动用 build 指向的 Dockerfile 路径构建镜像,并使用该镜像启动服务容器。

如果同时指定了 image 和 build,那么 compose 会将 build 出来的镜像命名为 image。

用法:

build: ./nginx
# 设定上下文目录
build:
  context: ./
  Dockerfile: nginx/Dockerfile
  1. args

和 Dockerfile 中的 ARG 用法一样,在构建中指定环境变量,构建完成后取消。 args 中的变量可以为空值。

注意:如需要在 yaml 中使用布尔值(true,false, yes,no等)必须要用引号括起来。

用法:

args:
  - version=1.0
  - boolean='true'
  - emptyvar
  1. command

可以覆盖启动容器后默认执行的命令。

用法:

command: nginx
command: [nginx, -g, deamon off]
  1. container_name

设置容器的名称,默认为:

用法:

container_name: lnmp_nginx
  1. depends_on

设置依赖。有时候某个容器需要另外一个容器作为依赖,则该命令可以解决依赖前后问题。如启动 nginx 前要先启动 php-fpm,这时候只需要这么写:

depends_on:
  - php-fpm
  1. entrypoint

用法和 Dockerfile 中的ENTRYPOINT 一致,会覆盖 Dockerfile 中的 ENTRYPOINT。

  1. environment

设置镜像中的环境变量,可以被保存在镜像当中,即每次启动容器,这些变量依旧存在容器当中。写法和 args 一致:

environment:
  - MYSQL_ROOT_PASSWORD: 123456
  1. expose

暴露容器中的端口,和 Dockerfile 中的EXPOSE 用法一致。

  1. links

    类似于 docker run 中的 —link 参数,用于连接容器。如 nginx 容器需要连接 php-fpm 的容器,只需要这么写:

    links:
      - php7-fpm:php
    

    其中,php 为 nginx 容器中连接 php 的别名,php7-fpm 为 php-fpm 服务的名字。

  2. ports

    用于映射端口,用法和 docker run 的参数 -p 一致:

    ports:
      - "8888:80"
    

    将容器的 80 端口映射到宿主机的 8888 端口中。

  3. volumes

    挂载一个目录或者一个数据卷容器到 container 中。数据卷的路径可以是绝对的,相对的。

    用法: [HOST:CONTAINER] or [HOST:CONTAINER:rw] rw的意思是,容器对该卷可读可写;ro为只读。

    volumes:
      # 只在容器中创建一个数据卷
      - /website/html
      # 绝对路径
      -	/home/website:/website/html
      # 相对路径
      -	./data:/website/html
      # 已存在的数据卷容器,并设置权限为只读
      - data_container:/website/html:ro
    
  4. volumes_from

    从其他容器或者服务挂载数据卷,可选参数为 :ro 只读 或者 :rw 可读可写。默认为可读可写。

  5. networks

    指定容器加入的网络:

    services:
      nginx:
        networks:
          web_app
    

    web_app 为网络名称。

还有其他的配置项,具体的可以去 官网查看

编写一个多容器配置

先创建如下目录:

./
├── conf			// 配置文件目录
│   ├── mysql
│   ├── nginx
│   └── php
├── data			// mysql 数据目录
├── logs			// 日志文件目录
│   ├── mysql
│   ├── nginx
│   └── php
└── www				// 项目目录

新建一个 docker-compose.yml 文件:

version: '2'
services:
  nginx:
    image: nginx:1.13
    ports: 
      - "80:80"
    volumes:
      - ./www:/usr/share/nginx/html:rw
      - ./logs/nginx/:/var/log/nginx:rw
      - ./conf/nginx/conf.d:/etc/nginx/conf.d:ro
    links:
      - php:fpm
    depends_on:
      - php

  php:
    build: ./conf/php
    ports: 
      - "9000:9000"
    volumes:
      - ./www:/usr/share/nginx/html:rw
      - ./logs/php/:/var/log/php:rw
    links:
      - mysql:mysql
    depends_on:
      - mysql
  mysql:
    image: mysql:5
    ports: 
      - "3306:3306"
    volumes:
      - ./mysql:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
      MYSQL_USER: "test"
      MYSQL_PASSWORD: "testpass"

version 为2 可以兼容旧版本的docker。

services 这里一共启动了3个服务:

  • nginx。监听 80 端口,挂载了 www 目录为工作目录,挂载 logs/nginx 为日志目录,挂载 conf/nginx/conf.d 至容器的 nginx 的配置文件夹。连接 php 容器,表示为 fpm。依赖于 php 容器。
  • php。 监听 9000 端口,挂载 www 目录为工作目录,挂载 logs/php 为日志目录,依赖于 mysql 容器并连接 mysql 容器。
  • mysql。监听 3306 端口,挂载 mysql 目录为 mysql 数据存储目录,并设置了3个环境变量,分别为 root密码,mysql 用户 test 并设置 test 的密码为 testpass。

配置文件自行添加,最终的目录结构为:

.
├── conf
│   ├── mysql
│   ├── nginx
│   │   └── conf.d
│   │       ├── default.conf
│   │       └── home.conf
│   └── php
│       ├── Dockerfile
│       └── php.ini
├── docker-compose.yml
├── logs
│   ├── mysql
│   ├── nginx
│   └── php
├── mysql
└── www
    ├── home
    │   └── index.html
    ├── index.html
    ├── index.php
    └── i.php

因为 php-fpm 我们需要做额外的事情,所以使用 Dockerfile 来构建镜像。php 的 Dockerfile 的内容配置和之前的 Dockerfile 一致:

FROM php:7.1-fpm

MAINTAINER LeungJZ

COPY php.ini /usr/local/etc/php/conf.d/php.ini

RUN docker-php-ext-install pdo_mysql

EXPOSE 9000

CMD ["php-fpm"]

可以在 RUN 命令中,安装需要的 php 拓展。

在项目根目录中运行命令 docker-compose up 开始构建。

leung@ubuntu:~/compose$ docker-compose up
Pulling mysql (mysql:5)...
5: Pulling from library/mysql
aa18ad1a0d33: Already exists
fdb8d83dece3: Pull complete
75b6ce7b50d3: Pull complete
ed1d0a3a64e4: Pull complete
8eb36a82c85b: Pull complete
41be6f1a1c40: Pull complete
0e1b414eac71: Pull complete
914c28654a91: Pull complete
587693eb988c: Pull complete
b183c3585729: Pull complete
315e21657aa4: Pull complete
Digest: sha256:0dc3dacb751ef46a6647234abdec2d47400f0dfbe77ab490b02bffdae57846ed
Status: Downloaded newer image for mysql:5
Building php
Step 1/6 : FROM php:7.1-fpm
 ---> 9b44e8b4c8b6
Step 2/6 : MAINTAINER LeungJZ
 ---> Running in e5c103cc2d37
 ---> c396815cf8b6
Removing intermediate container e5c103cc2d37
Step 3/6 : COPY php.ini /usr/local/etc/php/conf.d/php.ini
 ---> bc4a19e69f93
Removing intermediate container 566b27944ffb
Step 4/6 : RUN /usr/local/bin/docker-php-ext-install pdo_mysql
 ---> Running in 8ebd9dadf506
  ---> a3483051c1bb
Removing intermediate container 8ebd9dadf506
Step 5/6 : EXPOSE 9000
 ---> Running in 9a4f81103c0c
 ---> d0376a2a8bfe
Removing intermediate container 9a4f81103c0c
Step 6/6 : CMD php-fpm
 ---> Running in 8d7f61c657f9
 ---> 77072c6b2561
Removing intermediate container 8d7f61c657f9
Successfully built 77072c6b2561
Successfully tagged compose_php:latest
WARNING: Image for service php was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating compose_mysql_1 ...
Creating compose_mysql_1 ... done
Creating compose_php_1 ...
Creating compose_php_1 ... done
Creating compose_nginx_1 ...
Creating compose_nginx_1 ... done
Attaching to compose_mysql_1, compose_php_1, compose_nginx_1

不出1分钟,整个项目环境就已经搭建好了。根据提醒, php 服务已经被构建出来了,因为它一开始并不存在。如果想要重新构建整个服务,需要运行 docker-compose build or docker-compose up --build

这时 docker ps 查看:

leung@ubuntu:~$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
18bc61bd12b1        nginx:1.13          "nginx -g 'daemon ..."   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp       compose_nginx_1
38ccb807e09b        compose_php         "docker-php-entryp..."   About a minute ago   Up About a minute   0.0.0.0:9000->9000/tcp   compose_php_1
67188d651b80        mysql:5             "docker-entrypoint..."   About a minute ago   Up About a minute   0.0.0.0:3306->3306/tcp   compose_mysql_1

可以看到已经成功启动了三个容器。

通过浏览器访问:

docker-compose-success

可以发现已经运行成功,而且 php 文件也能正常执行。

该项目地址: 传送门

docker-compose 命令

docker 差不多,也有 start , stop, build , logs , rm 等常用命令,其作用也是类似的。

总结

docker 真是一个神器!!!

这只是一个简单的入门,希望大家能继续挖掘 docker 更强大的功能。