Docker-使用多个数据库组合

我试图找出如何使用 docker-compose. yml 和从 sql 转储导入的2个数据库来实现 docker。

httpd:
container_name: webserver
build: ./webserver/
ports:
- 80:80
links:
- mysql
- mysql2
volumes_from:
- app


mysql:
container_name: sqlserver
image: mysql:latest
ports:
- 3306:3306
volumes:
- ./sqlserver:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dbname1
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass


mysql2:
extends: mysql
container_name: sqlserver2
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dbname2
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass


app:
container_name: webdata
image: php:latest
volumes:
- ../php:/var/www/html
command: "true"

以上结果如下:

Kronos:mybuild avanche$ ./run.sh
Creating sqlserver
Creating webdata
Creating sqlserver2


ERROR: for mysql2  driver failed programming external connectivity on endpoint sqlserver2 (6cae3dfe7997d3787a8d59a95c1b5164f7431041c1394128c14e5ae8efe647a8): Bind for 0.0.0.0:3306 failed: port is already allocated
Traceback (most recent call last):
File "<string>", line 3, in <module>
File "compose/cli/main.py", line 63, in main
AttributeError: 'ProjectError' object has no attribute 'msg'
docker-compose returned -1

基本上,我试图在一个 docker 组合文件中建立整个堆栈,创建2个数据库并导入各自的 sql 转储。 有人有什么建议吗?

101442 次浏览

您正在尝试将两个数据库容器绑定到同一个端口 -3306,这基本上是不可能的。 您需要更改其中一个数据库的端口映射,例如 mysql保留 3306:3306,而 mysql2应该使用 3307:3306

只是告诉其他可能调查此事的人。

我解决这个问题的方法是:

MYSQL_DATABASE: dbname

并将相关的 create 数据库语句直接添加到传递给 Docker-entrypoint-initdb. d的 sql 文件中。

在这个阶段,sql 命令是在 root 下执行的,因此您还需要添加一条语句,以便向您想要使用的数据库用户授予相关权限。

version: '3'
services:
mysql1:
image: mysql:5.6.26
environment:
MYSQL_ROOT_PASSWORD: asdf
MYSQL_USER: asdf
MYSQL_HOST: localhost
MYSQL_PASSWORD: asdf
MYSQL_DATABASE: asdf
ports:
- "3307:3306"
mysql2:
image: mysql:5.6.26
environment:
MYSQL_ROOT_PASSWORD: asdf
MYSQL_USER: asdf
MYSQL_HOST: localhost
MYSQL_PASSWORD: asdf
MYSQL_DATABASE: asdf
ports:
- "3308:3306"
  • docker-compose up之后
  • 连接 mysql1

    mysql -h localhost -uasdf -P 3307 -pasdf asdf --protocol=tcp -D asdf
    
  • Connect to mysql2

    mysql -h localhost -uasdf -P 3308 -pasdf asdf --protocol=tcp -D asdf
    

单个 Docker 容器中的多个数据库

本页其他地方的答案为每个数据库设置了一个专用容器,但是一个 MySQL 服务器能够托管多个数据库。是否应该使用 是另一个问题,但是如果希望在单个容器中使用多个数据库,则使用 举个例子

译文:

version: '3'


volumes:
db:
driver: local


services:
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/provision/mysql/init:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: local

Docker/provision/mysql/init/01-database. sql:

# create databases
CREATE DATABASE IF NOT EXISTS `primary`;
CREATE DATABASE IF NOT EXISTS `secondary`;


# create root user and grant rights
CREATE USER 'root'@'localhost' IDENTIFIED BY 'local';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

这是怎么回事?

这是因为 MySQL Docker 项目有一个 入口点脚本,如果存在的话,它将运行 /docker-entrypoint-initdb.d文件夹中的所有文件。这对于设置数据库和初始化它们的模式和数据非常有用。在 docker-compose 中,我们使用 volumes将该虚拟文件夹映射到主机系统上的一个文件夹。

对我来说,接下来的帮助是:

  db:
image: postgres
container_name: mgt_db
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_DB: mgtdb
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
db2:
image: postgres
container_name: pay_vault_db
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_DB: payvaultdb
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5433:5432

在挣扎了3天后,我发现了这篇文章 解决这个问题救了我的命

文件结构

Project
├── docker-compose.yml (File)
├── init (Directory)
│   ├── 01.sql (File)

然后指向 docker-compose. yml 文件中卷内的 init 目录,如下所示

volumes:
- ./init:/docker-entrypoint-initdb.d

01

CREATE DATABASE IF NOT EXISTS `test`;
GRANT ALL ON `test`.* TO 'user'@'%';

码头作曲

version: '3.6'
    

services:
# MySQL
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydb
MYSQL_USER: user
MYSQL_PASSWORD: user


volumes:
- ./init:/docker-entrypoint-initdb.d
    

adminer:
image: adminer
restart: always
ports:
- 8080:8080

在一个容器中运行多个服务

在我看来,以上的答案没有一个是完整的, 我看到有人试图启动两个集装箱。运行两个数据库容器是好还是坏?Docker 的文件上说

通常建议通过对每个容器使用一个服务来分离关注领域。 该服务可能分叉成多个进程(例如,Apache HTTP Server 启动多个工作进程)。有多个进程是可以的, 但是为了从 Docker 中获得最大的好处,避免一个容器负责整个应用程序的多个方面。 您可以使用用户定义的网络和共享卷连接多个容器。

将同样的规则也应用于数据库似乎在逻辑上是正确的。因此,对每个模式使用数据库容器没有什么错误。它提供了灵活性。

下面我添加了更多的网络和固定数据库初始化 通过扩展‘ mysql’容器,将相同的3306端口暴露在外部 提供从控制台或外部应用程序对 mysql 数据库的访问。 该端口必须是唯一的 这些端口提供对数据库的访问 控制台或外部应用程序。如果数据库访问要求从应用程序 容器,则不需要这些映射 内部 DNS。这就是为什么应用程序容器的数据库连接可以是 通过使用容器名称作为域名来配置 连接字符串将是 dbuser@mysql: 3306/dbname1和 Dbuser@mysql2:3306/dbname2.

version: '3'
services:


httpd:
container_name: webserver
build: ./webserver/
ports:
- 80:80
links:
- mysql
- mysql2
volumes_from:
- app
   

mysql:
container_name: sqlserver
image: mysql:latest
ports:
- 3306:3306
volumes:
- ./dump.sql:/docker-entrypoint-initdb.d/dump.sql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dbname1
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass
networks:
- app-network
   

mysql2:
extends: mysql
container_name: sqlserver2
ports:
- 3307:3306
volumes:
- ./dump2.sql:/docker-entrypoint-initdb.d/dump.sql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: dbname2
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass
networks:
- app2-network


app:
container_name: webdata
image: php:latest
volumes:
- ../php:/var/www/html
command: "true"
networks:
- app-network
- app2-network


#Docker Networks
networks:
app-network:
app2-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local

当您研究 mysql 图像的 /usr/local/bin/docker-entrypoint.sh时,您将注意到在映射的 docker-entrypoint-initdb.d中处理 *.sh文件的不同模式(寻找 HERE标记) :

        case "$f" in
*.sh)
if [ -x "$f" ]; then
"$f"
else
. "$f" # HERE!!
fi
;;
*.sql)    mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;; # HERE!!
# ...
esac

这样你就可以创建一个没有可执行位的 000-databases.sh,包含以下内容:

echo "
CREATE DATABASE IF NOT EXISTS \`other-database\`;
GRANT ALL PRIVILEGES ON \`other-database\`.* TO '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';
" | docker_process_sql

这里的关键实用程序是 docker_process_sql,它处理 SQL 脚本。

您可以在一个容器服务中拥有多个数据库:

docker-compose.yml

version: '3.7'
services:
postgres-db:
restart: always
image: postgres:latest
volumes:
- db-volume:/var/lib/postgresql/data
ports:
- "5432:5432"
env_file:
- ./db-prod.env

db-prod.env

POSTGRES_USER=myusername
POSTGRES_PASSWORD=mypassword
POSTGRES_MULTIPLE_DATABASES=db1,db2

资料来源: 1 2 3