我的docker随笔17:使用docker-compose启动MySQL、Redis和Mongo

一、背景

有网友咨询用docker-compose启动几个存储服务,这些服务包括了MySQL、Redis、Mongo。恰好笔记没做过这一方面,趁机会学习一下。

二、要求

需要启动的docker如下:

1
2
3
4
5
6
7
8
docker run -d --name myredis -v $PWD/data:/data -p 6378:6379 redis --appendonly yes

docker run --name=mysql -d -p 3306:3306 -e TZ=Asia/Shanghai \
--mount type=bind,source="$(PWD)"/data,target=/var/lib/mysql mysql/mysql-server:5.6 \
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci \
--explicit_defaults_for_timestamp=false

docker run -d --name mongo -p 27017:27017 mongo

分析如下:
除了常用的docker启动操作外,Redis需要添加持久化的配置,MySQL复杂很多,有时区,有挂载目录,有字符集编码配置。

三、实验

3.1 配置文件

先给出docker-compose文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
version: '2'
services:
# 第一个容器 mysql
foomysql:
# 镜像名,如果不存在,则从网络下载,如果网络不存在,则会出错
image: mysql:5.6
# 容器名,在运行名称是唯一的
container_name: foomysql
restart: always # 如果容器运行出错,则重启容器
# 挂载数据卷
volumes:
- $PWD/mysqldata:/var/lib/mysql
environment:
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=latelee
- MYSQL_PASSWORD=123456
# 端口映射
ports:
- "3306:3306"
# 启动时执行的命令
command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci', '--explicit_defaults_for_timestamp=false']
# 自定义的网络(见下[网络配置])
networks:
- foo-net

redis:
image: redis
container_name: fooredis
restart: always
volumes:
- $PWD/redisdata:/data
ports:
- "6379:6379"
command: ["redis-server", "--appendonly", "yes"]
networks:
- foo-net

mongo:
image: mongo
container_name: foomongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
networks:
- foo-net

mongo-express:
image: mongo-express
container_name: foomongo-express
restart: always
ports:
- 8081:8081
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
networks:
- foo-net


# 网络配置
networks:
foo-net: # foo-net是自定义的网络名称
driver: bridge # 桥接方式

挑几个要点说明如下:
1、挂载目录可以使用$PWD/代替当前目录,也可以直接使用./。当存在多个容器服务时,目录名称最好要有辨识度。
2、如果希望容器在启动的同时带有参数运行,则使用command来指定。如command: ["redis-server", "--appendonly", "yes"],即等于redis-server --appendonly=yes,对应到docker命令,是docker run -d --name myredis -v $PWD/data:/data -p 6378:6379 redis --appendonly yes,注意,这句命令应该如此阅读:docker run -d --name myredis-v $PWD/data:/data-p 6378:6379 redis--appendonly yes不能认为是redis --appendonly yes
3、mongo相关的环境变量,不能带前导的-,即正确的是:

1
2
3
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root

不能是:

1
2
3
environment:
- MONGO_INITDB_ROOT_USERNAME: root
- MONGO_INITDB_ROOT_PASSWORD: root

否则会提示:

1
2
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.mongo.environment contains {"MONGO_INITDB_ROOT_USERNAME": "root"}, which is an invalid type, it should be a string

3.2 运行

使用docker-compose up命令可以直接启动。如果不希望有输出信息,则使用docker-compose up -d来启动。启动后,使用docker-compose ps命令查看运行状态:

1
2
3
4
5
6
7
docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------
foomongo docker-entrypoint.sh mongod Up 27017/tcp
foomongo-express tini -- /docker-entrypoint ... Up 0.0.0.0:8081->8081/tcp
foomysql docker-entrypoint.sh mysql ... Up 0.0.0.0:3306->3306/tcp
fooredis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp

从信息上看,已经可以正常运行了。

3.3 分析

这里重要关注一下MySQL的字符集设置是否正确。操作如下,注释见中文:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
root@latelee:/home/latelee/docker/composefile/mysql_test# docker exec -it foomysql bash # 进入容器
root@61858ee65fd1:/# mysql -uroot -proot # 使用root进入MySQL
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.45 MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like '%character%'; # 查看字符集
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | utf8mb4 | ## !!!! 与配置的一致
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> show variables like 'collation%';
+----------------------+--------------------+
| Variable_name | Value |
+----------------------+--------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci | ## !!!! 与配置的一致
+----------------------+--------------------+
3 rows in set (0.00 sec)

mysql> select user from mysql.user; ## 查询用户
+---------+
| user |
+---------+
| latelee |
| root |
| root |
+---------+
3 rows in set (0.00 sec)

mysql> exit # 退出MySQL
Bye
root@61858ee65fd1:/# exit # 退出容器
exit

四、小结

针对网友的提问及本文的知识点,总结一下:
1、有些服务在启动时需要带参数,则可以在docker-compose文件中使用command来指定参数。
2、如果这样做还不能达到目的,则要考虑自行重新构建docker镜像,在启动文件中添加参数。
3、不同的服务,其运行的进程名称不同,如MySQL服务名为mysqld,Redis服务名为redis-server,这些知识只能在日常积累,需要参考官方的说明文档,没有规律可遵——其实接触使用多了,也就熟悉了。如果一定要找规律,Linux系统,守护进程(或服务进程)名称是以d结尾,d表示daemon
4、官方镜像都带有介绍详细的说明。包括如何用docker启动,如果配置docker-compose等等。请自行参阅。
5、项目需要同时使用多个docker容器时,强烈建议使用docker-compose来管理。
6、实际项目不同,功能不同,参数亦不同,本文内容仅作为参考。

五、扩展

1、本文所述“docker-compose文件”,——包括作者日常交流,都是指“docker-compose.yml”这个文件。而“docker-compose”则是指docker-compose这个工具本身。
2、默认情况下,直接使用docker-compose up -d命令启动即可。此时,docker-compose工具会在当前目录查找docker-compose.yml文件,并以目录名称作为工程名称。如果需要更改,则使用-f来指定docker-compose文件,-p指定工程名称。
3、docker-compose也有类似的

本文仅关注docker-compose的使用,对于MySQL、Redis、Mongo容器化未有深入研究,不作为实践的指导。如后续有机会,再进行研究。

附录

这是MySQL官方镜像及说明。
这是Redis官方镜像及说明。
这是Mongo官方镜像及说明。
这是mongo-express官方镜像及说明。