概念
docker-compose是官方开源项目,里面有两个很重要的概念,第一个是服务(一个应用的容器,实际上可以包含若干个运行相同镜像的容器实例),第二个是项目(由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml中定义)。
docker是一个轻量化程序,官方推荐每一个docker容器中只运行一个进程,如果一个应用涉及到MySQL,nginx等环境,那我们需要分别为应用,数据库和nginx创建单独的docker容器,然后分别启动容器。但每次启动应用,都需要docker run多次,或者写一些脚本实现,比较繁琐,也不方便镜像管理,所以就产生了docker-compose来解决此问题。
docker-compose文件
image
此字段用于指定容器运行的镜像,以下格式均可以:
bash
image: redis
image: redis:5
image: redis@sha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7
image: library/redis
image: docker.io/library/redis
image: my_private.registry:5000/redis
command
是给主程序传的参数,可以灵活修改主程序运行的配置。
bash
command: ["bundle","exec","thin","-p","3000"]
command: bundle exec thin -p 3000
entrypoint
entrypoint指的是容器的入口程序,比如说redis默认要启动redis-server,busybox默认要启动sh,此字段用于覆盖容器默认的entrypoint。
bash
entrypoint: /code/entrypoint.sh
bash
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
environment
用于添加环境变量,可以使用数组或者字典,或者布尔值(布尔值需要带引号,否则yml会将其解析为True或者False)。
bash
#map语法
environment:
RACK_ENV: development
SHOW: "true"
....
#数组语法
environment:
- RACK_ENV: development
- SHOW: "true"
....
networks
用于指定容器运行的网络。
- 配置容器网络:这里总共有三个网络,分别为front-tier,back-tier和admin,frontend(前端服务)中有front-tier和back-tier两个网络里的服务进行通信,monitoring(监控服务)只能和admin网络里的服务进行通信,backend(后端服务)可以和back-tier和admin两个网络里的服务进行通信,aliases是取别名,同网络的服务可以通过database来访问backend服务。
bash
services:
frontend:
image: awesome/webapp
networks:
- front-tier
- back-tier
monitoring:
image: awesome/monitoring
networks:
- admin
backend:
image: awesome/backend
networks:
back-tier:
aliases:
- database
admin:
aliases:
- mysql
networks:
front-tier:
back-tier:
admin:
- 配置网络驱动和子网信息:这里frontend服务加入了front-tier网络里,并且指定了IP,于是,无论容器重启了多少次,frontend服务在front-tier网络里的IP永远都是172.16.238.10。下方的network是在配置front-tier网络的网段信息,如果ipv4_address没有指定IP,那么要分配的IP就在这个网段里面取。
bash
services:
frontend:
image: awesome/webapp
networks:
front-tier:
ipv4_address: 172.16.238.10
networks:
front-tier:
ipam:
driver: default
config:
- subnet: "172.16.238.0/24"
volumes
用于将主机的数据卷或者文件挂载到容器里,格式为源路径:目标容器里的路径,这只能指定绑定卷。在完整语法下,是需要用type指定是绑定卷还是命名卷。
bash
#短语法
services:
db:
image: postgres:latest
volumes:
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
- "/localhost/data:/var/lib/postgresql/data"
#完整语法
services:
backend:
image: awesome/backend
volumes:
- type: volume
#命名卷
source: db-data
target: /data
volume:
nocopy: true
#绑定卷
- type: bind
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock
volumes:
db-data:
ports
用于指定端口映射。
- 完整语法:target表示容器内部的端口,host_ip表示宿主机绑定的IP,published表示宿主机对外暴露的端口,protocol表示协议类型,mode表示端口模式(host表示单机直接绑定)。
- 短语法:"3000"表示容器里的3000端口映射到宿主机随机端口,"3000-3005"表示容器的3000-3005端口映射到宿主机同范围随机端口,"8000:8000"表示容器的8000端口映射到宿主机的8000端口,"9090-9091:8080-8081"表示宿主机9090映射到容器的8080,9091映射到容器的8081,"127.0.0.1:8001:8001"表示仅绑定到宿主机本地的8001,外部无法访问。
bash
#完整语法
ports:
- target: 80
host_ip: 127.0.0.1
published: 8080
protocol: tcp
mode: host
- target: 80
host_ip: 127.0.0.1
published: 8000-9000
protocol: tcp
mode: host
#短语法
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
expose
用于暴露端口,但不映射到宿主机,只有在同网络下其他容器用容器名+这些端口进行访问。
bash
expose:
- "3000"
- "8000"
build
用于指定为构建镜像的上下文路径。
- 短语法:构建上下文路径为./dir,docker会自动在./dir目录下查找默认名为Dockfile的文件来构建镜像。
bash
version: "3.7"
services:
webapp:
build: ./dir
- 完整语法:context用于指定上下文路径,dockerfile用于指定构建镜像的Dockerfile文件名,args是传递给dockerfile的构建参数,labels为镜像添加元数据标签,用于标识镜像用途,归属等信息,方便管理和检索。
bash
version: "3.7"
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
depends_on
用于设置依赖关系。
- docker compose up是指以依赖性顺序启动服务,在下列例子中,会先启动db和redis,才会启动web。docker compose up server自动包含server的依赖项。比如说docker compose up web还将创建并且启动db和redis。docker compose stop是指按依赖关系停止服务,在下列例子中,web在db和redis之前停止。
bash
version: "3.7"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
services:
web:
build: .
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
redis:
image: redis
db:
image: postgres
- health check:会确保MySQL服务完全启动以后,才会启动web服务,test是健康检查的命令,尝试使用root账号多路并执行select 1,如果命令成功返回,就认为服务健康,interval是指每10s执行一次健康检查,timeout是指单次检查超时时间为5s,retries表示最多尝试10次,如果10次都失败,将服务标记为不健康。
bash
version: "3.8"
services:
web:
image: nginx:1.24.0
environment:
TEST: 1
depends_on:
mysql:
condition: service_healthy
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: "bit@123"
volumes:
- /data/maxhou/mysqldata/varlib/:/var/lib/mysql
healthcheck:
test: mysql --user=root --password='bit@123' -e "SELECT 1;"
interval: 10s
timeout: 5s
retries: 10
env_file
用于从文件添加环境变量,可以是单个值或者列表的多个值。
- 用于加载单前目录下名为.env的文件,将文件中所有键值对作为环境变量注入容器。
bash
env_file: .env
- 按顺序加载多个.env文件,后加载的同名环境变量会覆盖先加载的同名变量。
bash
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
命令
对于compose来说,基本的使用格式是:
bash
docker compose [options] command [args]
-f或者--file指定使用的compose模板文件,默认为docker-compose.yml,可以进行多次指定,默认会用后面的文件覆盖前面文件的同名配置。
-p或者--project-name指定项目名称,默认将当前执行命令所在目录名称作为项目名称。
up
用于自动构建镜像,创建 / 重建容器,启动服务并关联依赖,一键启动整个项目。
bash
docker compose up [options] [service...]
-d表示在后台运行服务器
--force-recreate强制重新创建容器,不能与--no-recreate同时使用
--no-recreate如果容器存在了,则不能重新创建
down
用于停止所有容器,并删除出容器和网络
bash
docker compose down [options] [service...]
-v或者--volumes删除容器同时删除目录映射
run
用于在指定服务容器上执行相关的命令,例如启动了一个Ubuntu服务器,执行ping docker.com的命令。
bash
docker compose run ubuntu ping docker.com
bash
docker composerun [ooptions] service [command[args]]
-d表示在后台运行容器
--name 名字 用于为容器指定一个名字
--entrypoint cmd默认覆盖容器的启动命令
-e key=val用于设置环境变量值,可多次使用选项来设置多个环境变量
-u用于指定运行容器的用户名或者id
--rm表示运行命令后自动删除容器
-p映射容器端口到本地主机
操作
基本操作
- 创建compose目录。
bash
mkdir -p /data/mydir/compose/base
cd /data/mydir/compose/base
- 进入base目录创建docker-compose.yml文件
bash
vim docker-compose.yml
- 输入内容
bash
version: 3.8
services:
web:
image: nginx:1.24.0
environment:
TEST: 1
ports:
- 8979:80
networks:
- mytestnet
volumes:
- ./mynginxhome:/usr/share/nginx/html
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: "bit@123"
networks:
- mytestnet
volumes:
- /data/maxhou/mysqldata/varlib/:/var/lib/mysql
healthcheck:
test: mysql --user=root --password='bit@123' -e "SELECT 1;"
interval: 10s
timeout: 5s
retries: 10
redis:
image: redis:7
networks:
- mytestnet
healthcheck:
test: redis-cli ping
interval: 10s
timeout: 5s
retries: 10
networks:
mytestnet:
- 检查语法格式,修改错误信息
bash
docker compose config

- 创建首页目录,编辑首页内容
bash
mkdir -p ./mynginxhome
cd mynginxhome
echo "hello world" > index.html
cd ..
- 启动服务,通过浏览器页面访问
bash
docker compose up -d


- 停止服务,启动服务,删除服务
bash
docker compose stop
docker compose start
docker compose down

部署自定义服务
- 创建一个项目文件夹demojdbc
- 设计一个表,写入两条数据,在demojdbc文件夹下插入新文件为init.sql,将文件导入数据库里使用
bash
drop database if exists test;
create database test default character set utf8mb4;
use test;
create table users(
sno int(11) default null,
sname varchar(50) default null
)engine=InnoDB default charset=utf8mb4;
insert into users (sno,sname) values (1,'zhangsan'),(2,'lisi');
bash
mysql -u root -p < init.sql
- 在demojdbc文件夹下创建一个pox.xml,配置maven项目。
bash
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
<relativePath/>
</parent>
<groupId>com.bit</groupId>
<artifactId>demojdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demojdbc</name>
<description>demojdbc</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!-- Spring Boot JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 创建java目录文件结构
bash
mkdir -p src/main/java/com/bit/demojdbc
mkdir -p src/main/resources
- 添加启动类
bash
vim src/main/java/com/bit/demojdbc/DemojdbcApplication.java
java
package com.bit.demojdbc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemojdbcApplication {
public static void main(String[] args) {
SpringApplication.run(DemojdbcApplication.class, args);
}
}
- 配置数据库信息
bash
vim src/main/resources/application.properties
bash
server.port=8080
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=你的密码
- 配置用户控制器,不再设计mapper内容,而是通过jdbc直接完成操作。
java
package com.bit.demojdbc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
JdbcTemplate jdbcTemplate;
@RequestMapping("/list")
@ResponseBody
public Object Users(){
return jdbcTemplate.queryForList("select * from users");
}
}
- maven打包
bash
mvn clean package -Dmaven.test.skip=true
- 运行包,在浏览器中访问8080端口正常访问
bash
java -jar target/demojdbc-0.0.1-SNAPSHOT.jar


- 编写docker-compose.yml
bash
version: "3.8"
services:
web:
image: nginx:1.24.0
ports:
- "8112:80"
networks:
- myhellonet
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
mysys:
condition: service_started
mysys:
image: openjdk:8
depends_on:
mysql:
condition: service_healthy
command: java -jar /app/demojdbc-0.0.1-SNAPSHOT.jar
volumes:
- ./app/:/app/
networks:
- myhellonet
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: "root"
networks:
- myhellonet
volumes:
- ./mysql/varlib/:/var/lib/mysql
- ./mysql/init/:/docker-entrypoint-initdb.d/
healthcheck:
test: mysql --user=root --password='root' -e "SELECT 1;"
interval: 10s
timeout: 5s
retries: 10
networks:
myhellonet:
- 创建工程和卷目录
bash
mkdir -p /data/maxhou/mycompose/prj16
cd /data/maxhou/mycompose/prj16
mkdir -p ./nginx/conf.d
mkdir -p ./app
mkdir -p ./mysql/varlib/
mkdir -p ./mysql/init/
- 将nginx反向代理配置bit.conf放入到./nginx/conf.d
bash
server {
listen 80;
location / {
# 转发到 mysys 容器的 8080 端口
proxy_pass http://mysys:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
- 将数据库初始化文件init.sql放入mysql/init目录,把应用jar包放到./app目录
- 启动项目,用浏览器访问nginx,可以看到用户信息正常返回。

部署WordPress服务
- 编写docker-compose.yml
bash
version: '3.8'
services:
db:
image: mysql:5.7
volumes:
- ./db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mywordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
healthcheck:
test: mysql --user=root --password='mywordpress' -e "SELECT 1;"
interval: 10s
timeout: 5s
retries: 10
wordpress:
depends_on:
db:
condition: service_healthy
image: wordpress:latest
ports:
- "8000:80"
restart: always
volumes:
- ./wordpress:/var/www/html
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
- 运行站点,访问web界面
bash
docker compose up -d

- 删除,释放空间
bash
docker compose down