上一篇创建了一个PHP的运行环境,现在需要一个MySQL服务,直接运行:
[email protected]:~# docker run --name rocket-mysql -v /home/rocketfish/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
就自动下载并得到一个mysql版本为5.7的服务镜像。
这时候,要运行一个Web服务我们需要运行两次的docker run才可以,如果还有更多的Web容器或其他的服务容器呢?
Docker官方提倡一个容器仅提供一个服务,多个服务/容器可以使用docker-compose来管理。
docker-compose本身是一个Python写的工具,可以直接通过pip安装:
[email protected]:~# sudo pip install --upgrade pip
如果你本地并没有Python环境,也可以采用docker-compose的docker镜像来运行:
[email protected]:/home/compose-web# curl -L https://github.com/docker/compose/releases/download/1.8.0/run.sh > /usr/local/bin/docker-compose
[email protected]:/home/compose-web# docker-compose --version
#开始下载镜像,建议用第一种
查看帮助
[email protected]:~# docker-compose -h
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
--verbose Show more output
-v, --version Print version and exit
-H, --host HOST Daemon socket to connect to
--tls Use TLS; implied by --tlsverify
--tlscacert CA_PATH Trust certs signed only by this CA
--tlscert CLIENT_CERT_PATH Path to TLS certificate file
--tlskey TLS_KEY_PATH Path to TLS key file
--tlsverify Use TLS and verify the remote
--skip-hostname-check Don't check the daemon's hostname against the name specified
in the client certificate (for example if your docker host
is an IP address)
Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pulls service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
这些命令包括了创建/启动/停止/暂停/继续运行容器。
首先要创建docker-compose.yml,这是一个YAML格式的文档
mkdir docker
cd docker
mkdir web
mkdir db
vim docker-compose.yml
内容如下:
version: '2'
services:
db:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: web
MYSQL_USER: root
MYSQL_PASSWORD: rootweb
volumes:
- ./db/data:/var/lib/mysql
web:
depends_on:
- db
image: nginx-php-fpm:phalcon
ports:
- "80:80"
restart: always
environment:
WEB_DB_HOST: db:3306
WEB_DB_PASSWORD: root
volumes:
- ./web/html:/var/www/html/
links:
- db
这里的environment定义了环境变量,比如host的MAC,就可以在docker容器的系统变量里面得到,各个编程语言都有获取系统环境变量的方法。这些变量也可以组织起来放在文件里面加载进去,参考这里。
这里的volumes定义了要映射进容器的文件或文件夹或者数据容器,可以参考这里。注意,多个容器共享同一个目录,会出现写冲突,比如MySQL,多个实例,数据目录需要分开。所以设计好你的程序,哪一部分是需要只读的(可以共享),哪一部分是需要写的;写的部分是否可以放到各自临时目录,或者其他公共服务里面。
运行并查看
[email protected]:/home/compose-web# docker-compose up -d
Creating network "composeweb_default" with the default driver
Creating composeweb_db_1
Creating composeweb_web_1
[email protected]:/home/compose-web# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------
composeweb_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp
composeweb_web_1 /start.sh Up 443/tcp, 0.0.0.0:80->80/tcp
#也可以使用原来的命令
[email protected]:/home/compose-web# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
efbdaf257748 nginx-php-fpm:phalcon "/start.sh" 13 seconds ago Up 11 seconds 0.0.0.0:80->80/tcp, 443/tcp composeweb_web_1
a6935d20911e mysql:5.7 "docker-entrypoint.sh" 14 seconds ago Up 13 seconds 0.0.0.0:3306->3306/tcp composeweb_db_1
docker-compose up -d ,将会在后台启动并运行所有的容器。
docker-compose仅仅提供了对多个docker服务的管理,仍然可以在这些容器上运行原来的docker命令。检查下web容器的IP:
[email protected]:/home/compose-web# docker inspect composeweb_web_1 | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "172.18.0.3",
然后访问:http://172.18.0.3/ 就可以看到web页面了。
如果想要停止服务,可以用docker-compose stop:
[email protected]:/home/compose-web# docker-compose stop db
Stopping composeweb_db_1 ... done
[email protected]:/home/compose-web# docker-compose stop web
Stopping composeweb_web_1 ... done
再次启动,得到相同名称的服务:
[email protected]:/home/compose-web# docker-compose up -d
Starting composeweb_db_1
Starting composeweb_web_1
各个容器的名称也可以在配置文件里面通过参数container_name来指定。
docker-compose的配置还有很多其他的参数,可以参考这里。比如刚才我们通过docker inspect来查找容器IP,也可以配置成静态IP:
version: '2'
services:
app:
image: nginx-php-fpm:phalcon
networks:
app_net:
ipv4_address: 172.18.0.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.18.0.0/24
gateway: 172.18.0.1
- subnet: 2001:3984:3989::/64
gateway: 2001:3984:3989::1
也可以自定义网络。
刚才我们的配置文件里面直接指定了镜像,也可以指定Dockerfile镜像构建,假如Dockerfile在web目录下面:
build:
context: ./web
或者直接指明Dockerfile:
build:
context: .
dockerfile: Dockerfile-alternate
实际上,docker-compose的配置已经覆盖了Dockerfile的配置项,也可以直接用于构建多个docker服务,比如指定运行的命令
command: [/bin/bash]
这里的入口程序,如果不能持续运行的话,运行完成后,docker就会退出。所以如果你需要可以后台运行的docker容器,那么入口程序,就必须保持一个程序在前台运行,不退出,比如运行crontab的镜像,入口程序可以是:
cron && bash
cron这个程序是在后台运行的,如果不配合前台程序bash,容器执行玩cron就会退出了。其他运行crontab的容器,大都是强制一个程序在前台不退出,比如这个:
cron && tail -f /var/log/cron.log
这里需要注意一下,通过docker设置的environment values在容器内的cli下面执行时取不到的,比如printenv,使用cron后台运行时取不到外部设置的变量,但是手动执行时又可以。这些外部环境变量只能在ENTRYPOINT或者CMD所执行的shell里面去设置,比如在CMD执行start.sh:
printenv | grep -E "^HOST" > /root/env.conf && cron && bash
Docker compose还可以跟Docker Swarm结合。
参考链接:
Install Docker Compose
Quickstart: Docker Compose and WordPress
YAML 模板文件
Introduction to Docker Compose Tool for Multi-Container Applications
Dockerfile基本结构
How to Get Environment Variables Passed Through docker-compose to the Containers
Access environment variables from crontab into a docker container
How can I access Docker set Environment Variables From a Cron Job
Dockerfile里指定执行命令用ENTRYPOING和用CMD有何不同?
What is the difference between CMD and ENTRYPOINT in a Dockerfile?
Docker difference between run, cmd, entrypoint commands