前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除
本节目录如下
[一、Docker Compose入门](#一、Docker Compose入门)
[1.1、为什么要使用 Docker Compose 部署容器](#1.1、为什么要使用 Docker Compose 部署容器)
[1.2、Docker Compose 的项目概念](#1.2、Docker Compose 的项目概念)
[1.3、Docker Compose 的工作机制](#1.3、Docker Compose 的工作机制)
[1.4、Docker Compose 的特点](#1.4、Docker Compose 的特点)
[1.5、Docker Compose 的应用场景](#1.5、Docker Compose 的应用场景)
[1.6、使用 Docker Compose 的基本步骤](#1.6、使用 Docker Compose 的基本步骤)
[2.1、安装Docker Compose](#2.1、安装Docker Compose)
[2.2、使用 Docker Compose 部署 WordPress](#2.2、使用 Docker Compose 部署 WordPress)
[五、使用Docker Compose部署和管理应用程序](#五、使用Docker Compose部署和管理应用程序)
[5.2、docker-compose build](#5.2、docker-compose build)
[5.3、docker-compose up](#5.3、docker-compose up)
[5.4、docker-compose down](#5.4、docker-compose down)
[5.6、docker-compose 的3个命令up、run和start](#5.6、docker-compose 的3个命令up、run和start)
[5.7、Docker Compose的环境变量](#5.7、Docker Compose的环境变量)
一、Docker Compose入门
1.1、为什么要使用 Docker Compose 部署容器
- 微服务架构:适合用容器实现,每个服务由一个容器承载
- 简化部署:避免使用冗长和复杂的docker命令
- 统一管理 :Docker Compose 通过声明式配置文件统一管理多容器应用程序
1.2、Docker Compose 的项目概念
- 项目 :表示一个应用程序,涵盖所有资源,由一组关联容器组成
- 服务 :表示子应用程序 ,运行一个镜像 ,定义容器运行的镜像和参数
- 容器:服务的副本,可运行多个实例以增减服务数量
1.3、Docker Compose 的工作机制
- Compose 文件 :YAML 格式,定义多容器应用
- docker-compose 命令 :处理 Compose 文件,基于 Docker 引擎部署应用
- docker-py:Python 软件,调用 Docker API 管理容器
1.4、Docker Compose 的特点
- 隔离环境:使用项目名称隔离,适用于开发、CI 服务器等
- 保留卷数据:确保卷中数据不丢失
- 仅重建更改的容器 :快速更改环境,提高效率
- 环境定制:支持变量,为不同环境定制编排
1.5、Docker Compose 的应用场景
-
软件开发环境:创建隔离环境,记录配置服务依赖
-
自动化测试环境 :创建隔离测试环境,快速启动和销毁
csdocker-compose up -d # 启动应用程序 ./run_tests # 运行测试 docker-compose down # 停止应用程序并删除相关的资源
-
单主机部署:部署到远程 Docker 引擎,如 Docker Machine 或集群
1.6、使用 Docker Compose 的基本步骤
- 定义环境 :使用Dockerfile定义应用程序环境。
- 定义服务 :使用Compose文件声明应用程序的启动配置。
- 启动应用 :执行 docker-compose up启动所有容器。
二、示例
2.1、安装Docker Compose
本机为Docker-ce包安装,已经安装好了。下面讲其他安装方式:
Docker Compose 有多种安装方式,推荐从 GitHub 仓库下载二进制文件进行安装。
步骤 1: 下载二进制文件
使用 curl命令从 GitHub 下载 Docker Compose 的二进制文件:
cs
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
步骤 2: 添加可执行权限
为下载的二进制文件添加执行权限:
cs
chmod +x /usr/local/bin/docker-compose
步骤 3: 测试安装
检查 Docker Compose 是否安装成功:
cs
docker-compose --version
如果需要卸载 Docker Compose,执行以下命令:
cs
rm /usr/local/bin/docker-compose
2.2、使用 Docker Compose 部署 WordPress
2.2.1、 定义项目
(1)创建项目目录并进入 :
cs
mkdir my_wordpress && cd my_wordpress
(2)在项目目录下创建docker-compose.yml文件,并定义服务:
cs
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
2.2.2、构建项目
在项目目录下执行以下命令以启动服务:
cs
docker-compose up -d
2.2.3、访问 WordPress
WordPress 将在 Docker主机的8000 端口上运行,可以通过浏览器访问并完成安装。
2.2.4、关闭和清理
关闭并删除容器和网络 ,同时保留卷中的数据:
cs
# 删除容器和网络
docker-compose down
# 如果要同时删除卷,执行:
docker-compose down --volumes
三、编写Compose文件
Compose是Docker Compose项目的配置文件,又称Compose模板文件。
3.1、YAML文件格式
3.1.1、特点
YAML是一种数据序列化格式,易于阅读和使用 ,尤其适合数据。有以下特点:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进只能使用空格 ,不能使用tab,不要求空格个数,但相同层级应当左对齐
- 使用符号"#"表示注释,YAML中只有行注释
- 字符串可以不用引号标注
- 每个冒号与 它后面所跟的参数 之间都需要一个空格
3.1.2、数据分类
-
标量 标量相当于常量 ,是YAML数据的最小单位 ,不可再分隔。YAML支持整数、浮点数、字符串、NULL、日期、布尔值和时间等多种标量类型
-
序列 序列就是列表 ,相当于数组,使用一个短横线加一个空格表示一个序列项,实际上就是一种字典格式:
cs- "3000" - "8000" # 流式语法: ["3000","8000"]
-
映射 映射相当于JSON中的对象,也使用键值对表示,只是冒号后一定要加一个空格,同一层缩进层次的所有键值对属于一个映射
csPACK_ENV: development SHOW: 'true' # 流式语法: {RACK_ENV: development,SHOW: 'true'}
映射可以嵌套映射:
csmysql: image: mysql:8 container_name: mysql8
映射可以嵌套序列:
csexpose: - "3000" - "8000"
序列可以嵌套序列
cs# 多个值可以用映射(数组)或字典表示。(数组格式) environment: RACK_ENV: development SHOW: 'true' # 在映射中的任何布尔值都需要包括在引号中,字典格式则不需要: environment: - RACK-ENV=development - SHOW=true
3.2、Compose文件结构
Compose文件使用缩进表示层次结构。
cs
version: '3.7' # 指定了 Compose 文件的版本
# 定义服务
services:
web:
image: nginx:alpine # 使用官方的nginx镜像
ports:
- "80:80" # 将容器的80端口映射到宿主机的80端口
volumes:
- web-data:/var/www # 将宿主机的web-data目录挂载到容器的/var/www目录
networks:
- webnet # 服务web将连接到webnet网络
db:
image: mysql:5.7 # 使用官方的mysql镜像
environment:
MYSQL_ROOT_PASSWORD: example # 设置环境变量,这里为root用户设置密码
MYSQL_DATABASE: mydb # 初始化一个数据库
volumes:
- db-data:/var/lib/mysql # 将宿主机的db-data目录挂载到容器的/var/lib/mysql目录
networks:
- webnet # 服务db将连接到webnet网络
# 定义网络
networks:
webnet: # 定义了一个名为webnet的网络
# 定义数据卷
volumes:
web-data: # 定义了一个名为web-data的卷
db-data: # 定义了一个名为db-data的卷
Compose文件可以包含4节:version、services、networks和volumes。
在这个示例中:
- version 指定了 Compose 文件的版本 ,这会影响文件中可用的语法和功能。必须指定
- services 部分定义了两个服务:web 和 db。每个服务都有自己的配置,如使用的镜像、端口映射、环境变量、挂载的卷和连接的网络。
- networks部分 定义了一个名为webnet的网络,它将被web和db 服务使用。
- volumes部分 定义了两个数据卷:web-data 和 db-data,它们分别用于 web服务的网页数据和 db服务的数据库数据。
3.3、服务定义
在services节中定义若干服务,每个服务实际上是一个容器,需要基于镜像运行。下面介绍部分常用键及选项
3.3.1、image
image键用于指定启动容器的镜像,可以是镜像名称或镜像ID,例如:
cs
image: redis
iamge: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a3hec234
若镜像不存在则从镜像注册中心拉取。若定义有build键,则将基于Dockerfile构建一个镜像。
3.3.2、build
build键用于定义构建镜像时的配置,可以定义包括构建上下文路径的字符串
cs
build: ./bir
也可定义一个对象
cs
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
如果image和build同时定义,那么Docker Compose会构建镜像并且将镜像命名为image键所定义的名称。
cs
# 镜像将从./dir中构建,被命名为webapp,并被设tagtest标签
build: ./dir
image: webapp:tagtest
build键下面可使用以下选项
- context:定义构建上下文路径,可以是包含Dockerfile的目录,或是访问git仓库的URL
- dockerfile:指定Dockerfile。
- args:指定构建参数,即仅在构建阶段访问的环境变量,允许是空值
3.3.3、depends_on
定义服务之间的依赖,解决容器依赖。启动先后的问题
cs
version: "3.7"
services:
web:
build:
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
- 按依赖启动服务:db和redis先于web启动执行docker-compose up <服务名>命令将自动包括该服务的依赖。
- 按依赖顺序停止服务:web先于db和redis停止
3.3.4、networks
默认下,会自动创建名为"[项目名]_default"的默认网络。服务的每个容器都会加入默认网络,该网络上的其他容器都可以访问。每项服务都可使用networks键指定要连接的网络,格式如下:
css
services:
some-service:
netowrks:
- some-network
- other-network
networks有一个特别的aliases选项,用来设置该网络上的别名:
cs
# 下面示例提供了三个服务:web、worker、db,以及两个网络:new和legacy,db服务可以通过new网络中的主机名db或别名database访问,也可以通过legacy网络中的主机名db或别名mysql访问
version: "3.7"
services"
web:
image: "nginx:alpine"
networks:
-new
worker:
image: "my-worker-image:latest"
networks:
-legacy
db:
image: mysql
networks:
new:
aliases:
- database
legancy:
aliases:
- mysql
networks:
new:
legacy:
要让服务加入一个现有的网络,可以使用external选项
cs
networks:
default:
external:
name: my-pre-existing-network
3.3.5、volumes
作为服务的下级键,用于定义要挂载的主机路径或命名卷
可以挂载一个主机上的路径作为单个服务定义的一部分,此时不要在volumes节中定义卷。如果要在多个服务之间重用一个卷,应使用volumes节定义一个命名卷,然后由volumes键引用。
cs
# 由Web服务使用的命名卷和一个为单个服务定义的绑定挂载(db 服务中volumes 字段所定义的第 1 个路径)。db 服务也使用一个名为 dbdata 的命名卷(db服务中 volumes字段所定义的第2个路径),只是命名卷采用的是字符串格式。命名卷必须在volumes节中定义。
version: "3.7"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
volume:
novopy: true
- type: bind
source: ./static
target: /opt/app/static
db:
image: postgres:latest
volumes:
- "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
- "dbdata:/var/lib/postgresql/data"
volumes:
mydata:
dbdata:
volumes键的定义有两种格式:长格式,使用多个选项定义,上述就是使用的长格式。另一种是短格式,直接使用"主机:容器"格式指定主机上的路径,或使用"主机:容器:ro"格式定义访问模式
cs
volumes:
# 仅定义一个路径,让Docker引擎自动创建一个匿名卷
- /var/lib/mysql
# 定义一个绝对路径映射(绑定挂载)
- /opt/data:/var/lib/mysql
# 定义主机上相对Compose文件的路径(绑定挂载)
- ./cache:/tmp/cache
# 定义相对于用户的路径(绑定挂载)
- ~/configs:/etc/configs/:ro
# 命名卷
- datavolume:/var/lib/mysql
3.3.6、其他常用键
- command:用于覆盖容器启动后默认执行的命令。
- entrypoint:用于覆盖容器的默认入口设置,将覆盖使用 Dockerfile 的 ENTRYPOINT 指令在服务镜像上设置的任何默认入口,并清除镜像上的任何默认命令。这意味着如果 Dockerfile 中有 CMD指令,也将被忽略。
- env_file:设置从外部文件中添加的环境变量。
- environment:用于添加环境变量。
- expose:用于暴露没有发布到主机的端口,只允许被连接的服务访问。仅可以指定内都端口。
- external_links:用于连接未在Compose 文件中定义,甚至是非 Dodker Compose 管理的容器,尤其是那些提供共享或通用服务的容器。
- ports:指定要暴露的端口。
- restart:定义容器重启策略。
3.4、网络定义
3.4.1、driver
定义用于此网络的网络驱动,默认驱动取决于Docker引擎的配置方式,单主机上bridge驱动,Swarm集群中overlay驱动:
cs
driver: overlay
3.4.2、external
设置网络是否在Docker Compose外部创建。
cs
# proxy是到外部网络的网关。这里没有创建一个名为"[项目名]_outside"的网络而是让Docker Compose查找一个名为outside的现有网络,并将proxy服务的容器连接到该网络。
version:"3.7"
services:
proxy:
build: ./proxy
networks:
- outside
- default
app:
build: ./app
networks:
- default
networks:
outside:
external: true
3.5、卷定义
cs
# 其中一个数据库的数据目录作为一个卷与其他服务共享,可以被周期性地备份。
version:"3.7°
services:
db:
image: db
volurmes:
- data-volume:/var/ib/db
backup:
image: backup-servicel
volumes:
- data-yolume:/var/ib/backup/data
volumes:
data-volume:
volumes节中定义的卷可以只需一个名称,不做其他具体配置,这种情形会使用Docker配置的默认驱动,也可以使用以下键进行具体配置。
3.5.1、driver
此键定义用于卷驱动 ,默认就是 Docker 所配置的驱动,多数情况下是 local(本地驱动)。如果驱动不可用,则执行docker-compose up命令创建卷时,Docker会返回错误。下面是一个简单的示例
cs
driver: foobar
3.5.2、external
该键用于设置卷是否在 Docker Compose 外部创建。如果设置为 true,则 docker-compose up命令不会尝试创建它,如果该卷不存在,则会引发错误。
cs
# Docker Compose 不会尝试创建一个名为"[项目名]_data"的卷,而是查找一个名称为data的现有卷,并将其挂载到db服务的容器中。
version: "3.7"
services:
db:
image:postgres
volumes:
- data:/var/lib/postgresql/data
volumes:
data:
external: true
四、示例
4.1、编写单个服务的Compose文件
使用Docker Compose部署MySQL8.0服务器:编写docker-compose.yml文件
cs
version: '3.7'
services:
mysql:
image: mysql:8
container_name: mysql8
ports:
- 3306:3306
command:
--default-authentication-plugin=mysql_native_passord
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
environment:
- MYSQL_ROOT_PASSWORD=root
volumes:
- /etc/localtime:/etc/localtime:ro
- volumes.mysql8-data:/var/lib/mysql
volumes:
volumes.mysql8-data: null
使用docker-compose conifg命令查看,并会以更规范的形式显示整个compose文件
bash
[root@docker test]# docker-compose config
name: test
networks:
default:
name: test_default
services:
mysql:
command: --default-authentication-plugin=mysql_native_passord --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --explicit_defaults_for_timestamp=true --lower_case_table_names=1
container_name: mysql8
environment:
- MYSQL_ROOT_PASSWORD=root
image: mysql:8
networks:
default: null
ports:
- mode: ingress
protocol: tcp
published: "3306"
target: 3306
volumes:
- bind:
create_host_path: true
read_only: true
source: /etc/localtime
target: /etc/localtime
type: bind
- source: volumes.mysql8-data
target: /var/lib/mysql
type: volume
volume: {}
version: "3.7"
volumes:
volumes.mysql8-data:
name: test_volumes.mysql8-data
启动该服务:
cpp
[root@docker-2322030238 test]# docker-compose up -d
[+] Running 1/3
⠧ Network test_default Created 0.7s # 创建网络
⠦ Volume "test_volumes.mysql8-data" Created 0.6s # 创建卷
✔ Container mysql8 Started
实验完毕,执行以下操作关闭并清理服务:
cpp
[root@docker-2322030238 test]# docker-compose down --volumes
[+] Running 3/0
✔ Container mysql8 Removed 0.0s
✔ Volume test_volumes.mysql8-data Removed 0.0s
✔ Network test_default Removed 0.1s
4.2、多个服务的Compose文件
示例:建立和运行一个简单的Django/PostgreSQL应用程序
4.2.1、定义项目组件
一个Dockerfile文件、一个Python依赖文件和一个名为docker-compose.yml的Compose文件
(1)创建项目目录
bash
mkdir django-pg && cd django-pg
(2)创建并编辑Dockerfile文件
cs
# 从Python3父镜像开始
FROM python:3
ENV PYTHONUNBUFFERED 1
# 在镜像中添加code目录
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
# 在镜像中安装由requirement.txt文件指定要安装的Python依赖
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
COPY . /code/
(3)创建并编辑requirements.txt文件
cpp
Django>=2.0,<3.0
psycopg2>=2.7,<3.0
(4)创建并编辑docker-compose.yml文件
cpp
version: '3'
services:
db:
image: postgres
volumes:
- db_data:/var/lib/postgresql
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
volumes:
db_data: {}
4.2.2、创建Django项目
(1)切换到项目目录的根目录
(2)执行docker-compose run命令创建Django初始项目
cpp
docker-compose run web django-admin startproject myexample .
(3)查看所创建的项目目录的内容
cpp
[root@docker-2322030238 django-pg]# ls -l
total 16
-rw-r--r-- 1 root root 281 May 12 11:44 docker-compose.yml
-rw-r--r-- 1 root root 324 May 12 11:56 Dockerfile
-rwxr-xr-x 1 root root 629 May 12 12:07 manage.py
drwxr-xr-x 2 root root 74 May 12 12:07 myexample
-rw-r--r-- 1 root root 36 May 12 11:36 requirements.txt
容器以root身份运行,可执行以下命令修改这些文件的所有者
Delphi
chown -R $USER:$USER
4.2.3、连接数据库
(1)编辑项目目录中的myexample/settings.py文件,将其中的"DATABASES"定义修改如下:
cs
DATABASES={
'default':{
'ENGINE':'django.db.backends.postgresql',
'NAME':'postgres',
'USER':'postgres',
'PASSWORD':'postgres'
'HOST':'db',
'PORT':'5432',
}
}
这些设置由docker-compose.yml文件所指定的postgres镜像所决定。保存关闭
(2)在项目目录的根目录下执行docker-compose up命令
cs
docker-compose up
出现问题,待解决......
五、使用Docker Compose部署和管理应用程序
5.1、Compose命令行格式
cs
docker-compose [-f <arg>...][选项][命令][参数...]
- -f(--file): 指定一个或多个Compose文件的名称和路径
- -p(--project-name): 指定项目名称
- --project-directory: 指定项目路径
- --verbose: 输出更多调试信息
- --log-level: 设置日志级别
- -v(-version): 显示Docker Compose命令的版本信息
- -h(--help): 获取Compose命令行的帮助信息
5.2、docker-compose build
构建或重新构建服务并设置标签
cs
docker-compose build [选项][--build-arg 键=值·...][服务...]
- --compress: 使用gzip压缩构建上下文
- --force-m:删除构建过程中的临时容器
- --no-cache: 构建镜像的过程中不使用缓存
- --pul:总是尝试拉取最新版本的镜像
- --build-arg key=val:为服务设置构建时变量
5.3、docker-compose up
构建镜像,创建、启动和连接指定的服务容器
cs
docker-compose up [选项][--scale 服务=数值·...][服务...
- -d(--detach):分离模式,后台运行服务容器
- --quiet-pull:拉取镜像时不输出信息
- --no-deps:不启动所连接的服务
- --force-recreate:强制重新创建容器
- --no-recreate:如果容器已存在,则不重新创建
- --no-build:不构建缺失的镜像
- --no-start:创建服务后不启动它们
- --build:启动容器前构建镜像
5.4、docker-compose down
停止容器并删除由docker-compose up命令启动的对容器、网络、卷和镜像。默认情况下只有以下对象会被删除
- Compose文件中定义的服务的容器
- Compose文件中networks节所定义的网络
- 所使用的默认网络
外部定义的网络和卷不会删除,使用--volumes可以删除由容器使用的数据卷
cs
docker-compose down --volumes
5.5、其他常用的docker-compose命令
- start: 启动已存在的容器。
- stop:停止运行的容器。
- pause: 暂停容器。
- unpause: 恢复暂停的容器。
- kill:发送信号终止容器。
- run:为服务执行一次性命令。
- ps:查看当前运行的容器。
- exec:在容器中执行命令。
- rm:删除停止状态的容器。
5.6、docker-compose 的3个命令up、run和start
- up:启动或重新启动所有服务。
- run:运行一次性或临时任务。
- start:仅重启已创建但已停止的容器。
5.7、Docker Compose的环境变量
环境变量的优先级:
- Compose文件中直接设置的值。
- 环境文件。
- Shell环境变量。
- Dockerfile中的ARG或ENV指令。
- 未定义的变量。
举例:环境文件和Compose文件设置同一环境变量。环境文件./Docker/api/api.env中:
cs
NODE_ENV=test
Compose文件docker-compose.yml中:
cpp
version: '3'
services:
api:
image: 'node:6-alpine'
env_file:
- ./Docker/api/api.env
environment:
- NODE_ENV=production
运行容器时,会优先使用Compose文件中的环境变量
cs
docker-compose exec api node
> process.env.NODE_ENV
'production'
只有Compose文件中没有使用environment或env_file键时,Dockerfile文件中的ARG或ENV指令设置才会生效
5.8、组合使用多个Compose文件
- 基础Compose文件定义基本配置
- Override文件覆盖或新增服务配置
- 使用
-f
选项指定文件列表,Docker Compose将按顺序合并配置
5.8.1、合并配置规则
- 单值键:新值替换旧值。
- 多值键:两组值连接。
- environment、labels、volumes和devices:优先使用本地定义的值。
致谢
在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。
学习永无止境,让我们共同进步!!