一个计算机技术爱好者与学习者

0%

好好学Docker:Docker-Compose入门篇

1. Docker-Compose简介

Docker-Compose(简称Compose)是用于定义和运行多容器Docker应用程序的工具。
通过Compose,可以使用YAML文件来配置应用程序的服务。然后使用一个命令,就可以从配置中创建并启动所有服务。

本文中,我们来学习一下Compose的基础用法。

参考文档:

2. 安装Compose

在CentOS7机器上,假设已经了Docker,参考Install Docker Compose安装Compose-Docker。如果没有安装Docker,那么参考Docker入门进行安装。

1、安装docker-compose 1.24.1 版本

1
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

2、添加执行权限

1
2
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

3、验证安装

1
docker-compose --version

3. Compose运行容器

1、定义 docker-compose.yml

1
2
3
4
5
6
7
8
version: '3'
services:
nginx:
image: nginx:latest
container_name: vk-nginx
ports:
- "80:80"
- "443:443"

2、启动容器
在 docker-compose.yml 文件所在目录,执行命令

1
docker-compose up -d

执行之后,会启动一个名为 vk-nginx 的容器,主机端口80映射到容器端口80,主机端口443映射到容器端口443。

上面的配置和启动命令,实际上相当于

1
2
3
4
docker run --name vk-nginx -d \
-p 80:80 \
-p 443:443 \
nginx:latest

4. Compose常用命令

4.1. 创建/销毁容器

1
2
3
4
5
6
7
8
9
10
11
12
# 创建并运行容器
docker-compose up

# 创建并后台运行容器
docker-compose up -d

# 关闭并删除容器
docker-compose down

# 关闭并删除容器,连带删除容器挂载卷
docker-compose down -v
docker-compose down --volumes

4.2. 启动/停止容器

1
2
3
4
5
# 关闭容器但不删除容器
docker-compose stop

# 启动容器
docker-compose start

4.3. 查看容器

1
2
3
4
5
6
# 查看容器
docker-compose ps
docker-compose ps -a

# 查看web服务的环境变量
docker-compose run web env

5. Compose常用配置

5.1. 自定义启动命令

1
2
3
4
5
6
version: '3'
services:
test:
image: alpine:latest
container_name: test
command: ['tail','-f','/dev/null']

5.2. 使用环境变量

1
2
3
4
5
6
7
8
9
10
11
version: '3'
services:
test:
image: alpine:latest
container_name: test
command: ['tail','-f','/dev/null']
environment:
MYSQL_HOST: '192.166.56.100'
MYSQL_PORT: '3306'
MYSQL_USER: 'root'
MYSQL_PASSWORD: 'mysql123'

5.3. 容器挂掉后自动拉起

1
2
3
4
5
6
7
version: '3'
services:
test:
image: alpine:latest
container_name: test
command: ['tail','-f','/dev/null']
restart: always

5.4. 使用volume

docker使用持久化存储的时候,有两种方式:

  • bind mount方式:挂载宿主机的绝对路径(目录和文件都可以)到容器
  • volume方式:挂载volume(本质是目录)到容器

使用bind mount方式,如果宿主文件夹是空的,不光容器内的文件不会被复制到宿主机器上,容器的内容还会被覆盖为空,对于一些容器内路径文件夹存放config文件的情况,宿主目录为空会导致容器内的对应目录被清空,造成启动错误的问题。
使用volume方式,容器内的文件会被保留在volume中(对应的_data文件夹)内部,也就是文件被复制到宿主机器上.

两种方式都可以使用-v(–volume)和–mount参数,但是,在创建bind mount的时候,使用–volume会自动创建宿主方的文件夹,而–mount不会,因此使用–mount映射不存在的目录,会报错。

docker-compose指定的时候,有一些区别:

  • 使用bind mount的时候,宿主这边可以使用相对路径了(./),不需要显示指定($PWD)
  • 可以在指定volume名称的同时创建volume,需要使用volume:的配置项

以下是一个使用volumes的示例:

1
2
3
4
5
6
7
8
9
10
services:
...
dolphinscheduler-master:
volumes:
- dolphinscheduler-logs:/opt/dolphinscheduler/logs
- dolphinscheduler-shared-local:/opt/soft
#- /xxx/mysql-connector.jar:/opt/dolphinscheduler/libs/mysql-connector.jar
- type: bind
source: /xxx/mysql-connector.jar
target: /opt/dolphinscheduler/libs/mysql-connector.jar

参考文档:

5.5. 使用expose和ports

参考文档:

5.5.1. expose

expose暴露的端口,可由连接到同一网络的其他服务访问,但不会在宿主机上发布。
例如:

1
2
3
4
5
6
7
8
9
10
services:
myapp1:
...
expose:
- "3000"
- "8000"
myapp2:
...
expose:
- "5000"

docker ps结果如下:

1
2
3
CONTAINER ID   IMAGE    COMMAND     CREATED     STATUS      PORTS               NAMES
8673c14f18d1 ... ... ... ... 3000/tcp, 8000/tcp bael_myapp1
bc044e180131 ... ... ... ... 5000/tcp bael_myapp2

5.5.2. ports

ports暴露的端口,可由连接到同一网络的其他服务访问,并在宿主机上发布。
例如:

1
2
3
4
5
6
7
8
9
10
services:
myapp1:
...
ports:
- "3000" # container port (3000), assigned to random host port
- "3001-3005" # container port range (3001-3005), assigned to random host ports
- "8000:8000" # container port (8000), assigned to given host port (8000)
- "9090-9091:8080-8081" # container port range (8080-8081), assigned to given host port range (9090-9091)
- "127.0.0.1:8002:8002" # container port (8002), assigned to given host port (8002) and bind to 127.0.0.1
- "6060:6060/udp" # container port (6060) restricted to UDP protocol, assigned to given host (6060)

docker ps结果如下:

1
2
3
4
5
CONTAINER ID   ... PORTS                                                                        NAMES
e8c65b9eec91 ... 0.0.0.0:51060->3000/tcp, 0.0.0.0:51063->3001/tcp, 0.0.0.0:51064->3002/tcp, bael_myapp1
0.0.0.0:51065->3003/tcp, 0.0.0.0:51061->3004/tcp, 0.0.0.0:51062->3005/tcp,
0.0.0.0:8000->8000/tcp, 0.0.0.0:9090->8080/tcp, 0.0.0.0:9091->8081/tcp
127.0.0.1:8002->8002/tcp, 0.0.0.0:6060->6060/udp

ports长语法:

1
2
3
4
5
6
7
8
9
10
services: 
myapp1:
...
ports:
# - "127.0.0.1:6060:6060/udp"
- target: 6060
host_ip: 127.0.0.1
published: 6060
protocol: udp
mode: host

5.5.3. 小结

这两种暴露方式,最大的区别在于是否在宿主机上暴露端口,是否对外部网络提供服务。
使用docker ps查看容器时,根据PORTS字段,我们也能判断出该容器是否在宿主机上暴露端口。

但是,个别情况下,虽然我们看到的是端口是3000/tcp,但是依然可能在宿主机上暴露端口。可能是docker/docker-compose某个版本的bug,也可能是yaml文件中的version不匹配,也可能是其他什么原因。
这种情况下,只能找到docker-compose.yml,查看端口映射关系,然后查看宿主机端口开放情况。

5.6. 共享IPC

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3'
services:
first:
image: busybox
ipc: shareable
container_name: share_container
command: ['tail','-f','/dev/null']
second:
image: busybox
ipc: 'container:share_container'
command: ['tail','-f','/dev/null']
depends_on:
- 'first'

6. Docker-Compose网络问题

6.1. 问题描述

宿主机执行 docker-compose up -d 之后,宿主机突然无法从其他主机 ping 通了。

6.2. 问题排查

查看路由,发现路由中存在和主机网络冲突的路由。

1
2
ip route
route -n

查看docker网段使用情况,发现冲突的路由是由docker compose创建的。

1
2
docker network list
docker network inspect xxx

6.3. 原因分析和解决办法

原因分析:docker-compose up的时候,会自动创建一个网桥,占用一个网段,并且添加路由规则。
如果这个网段和现有网段发生了冲突,就会导致一些非预期的网络问题,比如主机突然访问不通了。

解决办法:指定容器网段。详情参考docker-compose up使用自定义的网段的两种方式

例如指定compose启动的容器网段为 192.168.51.0/24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '2.3'
networks:
harbor:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.51.0/24
gateway: 192.168.51.1
services:
registry:
image: goharbor/registry-photon:v2.3.3
container_name: registry
restart: always
...
networks:
- harbor
  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-docker-compose/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~