一、背景
有網友諮詢用docker-compose啓動幾個存儲服務,這些服務包括了MySQL、Redis、Mongo。恰好筆記沒做過這一方面,趁機會學習一下。
二、要求
需要啓動的docker如下:
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文件,如下:
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相關的環境變量,不能帶前導的-
,即正確的是:
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
不能是:
environment:
- MONGO_INITDB_ROOT_USERNAME: root
- MONGO_INITDB_ROOT_PASSWORD: root
否則會提示:
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
命令查看運行狀態:
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的字符集設置是否正確。操作如下,註釋見中文:
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官方鏡像及說明。