docker-compose具有多个数据库

docker-compose with multiple databases

我试图弄清楚如何使用docker-compose.yml和2个从sql dumps导入的数据库来实现docker。

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
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"

上面返回以下内容:

1
2
3
4
5
6
7
8
9
10
11
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 compose文件中获取整个堆栈设置,创建2个数据库并导入相应的sql转储。
有人有什么建议吗?


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

此页面上其他位置的答案为每个数据库设置了专用容器,但是单个MySQL服务器能够托管多个数据库。是否应该是另一个问题,但是如果要在单个容器中使用多个数据库,请参见以下示例。

docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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-databases.sql:

1
2
3
4
5
6
7
# 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将该虚拟文件夹映射到主机系统上的文件夹。


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


只是对可能研究此问题的其他人的更新。

我通过以下方法解决了这个问题:

1
MYSQL_DATABASE: dbname

from docker-compose.yml,并将相关的create database语句直接添加到要传递到docker-entrypoint-initdb.d的sql文件中。

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

    1
    mysql -h localhost -uasdf -P 3307 -pasdf asdf --protocol=tcp -D asdf
  • 连接到mysql2

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


经过奋斗,三天后才发现这篇文章
解决此问题挽救了我的生命

文件结构

1
2
3
4
Project
a"?a"€a"€ docker-compose.yml (File)
a"?a"€a"€ init (Directory)
a"?   a"?a"€a"€ 01.sql (File)

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

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

01.sql

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

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

对我来说,接下来要帮助:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  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

在容器中运行多个服务

从我的angular来看,以上所有答案均不完整。在原始问题中,
我看到了尝试启动两个容器的尝试。运行两个数据库容器是好是坏? Docker文档说

It is generally recommended that you separate areas of concern by using one service per container.
That service may fork into multiple processes (for example, Apache web server starts multiple worker processes). Ita€?s ok to have multiple processes,
but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application.
You can connect multiple containers using user-defined networks and shared volumes.

在逻辑上也将相同的规则应用于数据库似乎是正确的。因此,每个架构使用数据库容器都没有错。它提供了灵活性。

下面我在更多地方添加了网络和固定数据库初始化
优雅的方式。通过扩展\\'mysql \\'容器,相同的3306端口暴露为外部
提供从控制台或外部应用程序对mysql数据库的访问。
该端口必须是唯一的。要解决此错误,我添加了端口映射
mysql2容器也是如此。这些端口提供对数据库的访问
控制台或外部应用程序。如果需要从应用程序访问数据库
仅容器,不需要这些映射。 Docker有自己的
内部DNS。这就是为什么可以为应用程序容器建立数据库连接的原因
通过使用容器名称作为域名进行配置。因此,数据库
连接字符串将为dbuser @ mysql:3306 / dbname1和
dbuser @ mysql2:3306 / dbname2。

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
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