docker-compose with multiple databases

时间:2016-08-29 10:35:24

标签: database docker docker-compose

我正在试图弄清楚如何使用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 compose文件中,创建2个数据库并导入相应的sql转储。 有人有什么建议吗?

8 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:12)

正如对可能会对此进行调查的任何其他人的更新。

我通过删除:

解决了这个问题
MYSQL_DATABASE: dbname 
docker-compose.yml

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

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

答案 2 :(得分:10)

在单个Docker容器中有多个数据库

本页其他位置的答案为每个数据库设置了专用容器,但是单个MySQL服务器能够托管多个数据库。是否应该KEY_RESIZE,但是如果要在单个容器中使用多个数据库,请is a different question

docker-compose.yml:

C++

docker / provision / mysql / init / 01-databases.sql:

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

这是如何工作的?

之所以可行,是因为here's an example有一个MySQL Docker project,它将在# 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 ON *.* TO 'root'@'%'; 文件夹(如果存在)中的所有文件中运行。这对于设置数据库以及初始化其架构和数据很有用。在docker-compose中,我们使用/docker-entrypoint-initdb.d将该虚拟文件夹映射到主机系统上的文件夹。

答案 3 :(得分:4)

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
    
  • 连接到mysql2

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

答案 4 :(得分:2)

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

PageFactory

答案 5 :(得分:2)

经过奋斗,三天后发现了这个Article 解决这个问题挽救了我的生命

文件结构

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

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

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

01.sql

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

docker-compose.yml

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

答案 6 :(得分:2)

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

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

<块引用>

通常建议您通过为每个容器使用一项服务来分隔关注区域。 该服务可能会分叉到多个进程中(例如,Apache Web 服务器启动多个工作进程)。可以有多个进程, 但要从 Docker 中获得最大收益,请避免一个容器负责整个应用程序的多个方面。 您可以使用用户定义的网络和共享卷连接多个容器。

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

下面我添加了更多的网络和固定数据库初始化 优雅的方式。通过扩展“mysql”容器,相同的 3306 端口被暴露为外部 提供从控制台或外部应用程序访问 mysql 数据库的权限。 该端口必须是唯一的。为了解决这个错误,我添加了端口映射 mysql2 容器也是如此。这些端口提供对数据库的访问 控制台或外部应用程序。如果需要从应用程序访问数据库 仅容器,不需要这些映射。 Docker 有自己的 内部 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

答案 7 :(得分:0)

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

        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 脚本。 MYSQL_* 变量来自您的 docker-compose.yml 环境配置。