【问题标题】:Create database on docker-compose startup在 docker-compose 启动时创建数据库
【发布时间】:2017-04-10 11:30:49
【问题描述】:

我想使用 docker-compose.yml 文件中的环境变量创建一个 MySQL 数据库,但它不起作用。我有以下代码:

# The Database
database:
  image: mysql:5.7
  volumes:
    - dbdata:/var/lib/mysql
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: secret
    MYSQL_DATABASE: homestead
    MYSQL_USER: root
    MYSQL_PASSWORD: secret
  ports:
    - "33061:3306"

有人能解释一下这个变量的功能吗?

【问题讨论】:

    标签: mysql docker-compose


    【解决方案1】:

    还有一个选项可以为mysql 容器提供一个初始化文件,该文件将在每次创建容器时应用。

    database:
        image: mysql:5.7
        ports:
            - "33061:3306"
        command: --init-file /data/application/init.sql
        volumes:
            - ./init.sql:/data/application/init.sql
        environment:
            MYSQL_ROOT_USER: root
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: homestead
            MYSQL_USER: root
            MYSQL_PASSWORD: secret
    

    此类文件 (init.sql) 可能包含您的初始数据库结构和数据 - 例如:

    CREATE DATABASE IF NOT EXISTS dev;
    CREATE DATABASE IF NOT EXISTS test;
    USE dev;
    CREATE TABLE IF NOT EXISTS (...);
    

    【讨论】:

    • /data/application/init.sql 这个文件应该位于宿主机中?还是在 mysql 容器内?
    • @MadhanAyyasamy 查看更新后的答案。由于/data/application/init.sql 是在容器中运行的mysql 的参数,因此路径也必须是“内部”。该文件可以通过绑定挂载到达那里。
    • 我可以运行多个sql文件吗?
    • 这将在容器上生成一个名为/data/application/init.sql目录除非该文件已存在于容器中。关于挂载主机文件以在容器中显示为文件,请阅读 docker docs 上的 bind mounts
    • @Matley docker-compose.yml 中的卷路径是相对于该文件的,所以如果它在根项目目录中并且我们的挂载包含./init.sql:/data/application/init.sql 那么init.sql 文件也必须在根目录中目录
    【解决方案2】:

    数据库可能已经初始化,配置存储在/var/lib/mysql。由于您为该位置定义了一个卷,因此配置将在重新启动后继续存在。 MySQL 映像不会一遍又一遍地重新配置数据库,它只会这样做一次。

    volumes: - dbdata:/var/lib/mysql

    如果您的数据库是空的,您可以通过执行docker-compose down -v 来重置数据库,其中-v 删除在卷部分中定义的卷。见https://docs.docker.com/compose/reference/down/。在下一个docker-compose up,MySQL 映像将重新启动,并使用您通过环境部分提供的配置初始化数据库。

    【讨论】:

    • 哦,是的!非常感谢,一定是这样,因为现在它正在从 env 中获取值。变量。
    • 非常感谢先生!我无法自动导入我的数据库 sql gz 文件,因为第一次没有它就已经创建了卷。 -v 参数解决了这个问题。
    • 天哪,这太有用了。我花了一整天的时间试图弄清楚为什么 docker up 没有创建数据库。 (它已被删除)。这解决了它。令人惊讶的是,docker stop $(docker ps -a -q)docker rm $(docker ps -a -q)docker rmi $(docker images -q) 并没有解决这个问题。我原以为核弹一切都会奏效。
    【解决方案3】:

    回答您的问题...

    我在构建新的 docker 容器时经常做的一件事是了解我从中提取的映像在构建时做了什么。

    在你的 docker-compose.yml 你有这个

    # The Database
    database:
      image: mysql:5.7
    

    这是您从中提取的图像,“mysql:5.7”

    Dockerhub 是一个存储库,您可以在其中找到这些图像的信息。

    谷歌搜索“mysql:5.7 dockerhub”

    第一个结果是https://hub.docker.com/_/mysql/

    你有你的图像 5.7,如果你点击 5.7 你有这个

    https://github.com/docker-library/mysql/blob/607b2a65aa76adf495730b9f7e6f28f146a9f95f/5.7/Dockerfile

    镜像中的 Dockerfile 是什么,大家可以看看构建镜像时发生的有趣的事情。

    其中之一是 ENTRYPOINT ["docker-entrypoint.sh"]

    这是图像准备好时执行的文件

    如果你在 repo 中上一层,你会看到这个文件

    https://github.com/docker-library/mysql/tree/607b2a65aa76adf495730b9f7e6f28f146a9f95f/5.7

    你可以看到你的环境变量被用来创建新的数据库等等......

    file_env 'MYSQL_DATABASE'
            if [ "$MYSQL_DATABASE" ]; then
                echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
                mysql+=( "$MYSQL_DATABASE" )
    fi
    

    【讨论】:

      【解决方案4】:

      官方 MySQL docker 镜像在其基础镜像中添加了对初始化脚本的支持。他们在 Docker Hub 页面上的“初始化新实例”下记录了该功能。

      以下是我为解决在 MySQL docker 映像中创建多个数据库和用户而采取的步骤:

      1. 在名为.docker 的本地目录中创建名为setup.sql 的init 文件(Docker 映像可识别.sh、.sql 和.sql.gz 文件)
      2. 将命令放在setup.sql 中(示例见下文)
      3. 将安装脚本挂载到docker-compose.yaml 文件中的目录f 中(参见下面的示例)
      4. 运行docker-compose up -d,MySQL 将运行setup.sql 中的代码

      注意:脚本将按字母顺序运行文件,因此请记住这一点。

      docker-compose.yaml 示例

      version: "3.5"
      services:
          mysql:
              image: mysql
              ports:
                  - 3306:3306
              environment:
                  MYSQL_ROOT_PASSWORD: SomeRootPassword1!
                  MYSQL_USER: someuser
                  MYSQL_PASSWORD: Password1!
                  MYSQL_DATABASE: somedatabase
              volumes:
                  - .docker/setup.sql:/docker-entrypoint-initdb.d/setup.sql
                  - db_data:/var/lib/mysql
      volumes:
          db_data:
      

      setup.sql 示例

      -- create the databases
      CREATE DATABASE IF NOT EXISTS projectone;
      
      -- create the users for each database
      CREATE USER 'projectoneuser'@'%' IDENTIFIED BY 'somepassword';
      GRANT CREATE, ALTER, INDEX, LOCK TABLES, REFERENCES, UPDATE, DELETE, DROP, SELECT, INSERT ON `projectone`.* TO 'projectoneuser'@'%';
      
      FLUSH PRIVILEGES;
      

      【讨论】:

      • 不起作用,我收到错误:myflashcards_db | 2020-04-08T18:51:57.851680Z 1 [错误] 无法打开引导文件 /data/application/init.sql myflashcards_db | 2020-04-08T18:51:57.851718Z 1 [错误] 1105 引导文件错误,返回代码 (0)。最近的查询:'SET @@sql_log_bin = @sql_log_bin;
      【解决方案5】:

      对于 docker-compose 的第 2 版,.yml.yaml 可能如下所示:

      version: '2'
      volumes:
       dbdata:
      
      services:
       mysql:
        image: mysql:5.7
        container_name: mysql
        volumes:
          - dbdata:/var/lib/mysql
        restart: always
        environment:
          - MYSQL_ROOT_PASSWORD=secret
          - MYSQL_DATABASE=homestead
          - MYSQL_USER=root
          - MYSQL_PASSWORD=secret
        ports:
          - "33061:3306"
      

      docker-compose up -d 开头 并检查:

      $ docker ps
      CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
      a3567fb78d0d        mysql:5.7           "docker-entrypoint..."   2 minutes ago       Up 2 minutes        0.0.0.0:33061->3306/tcp   mysql
      
      docker exec -it a3567fb78d0d bash
      root@a3567fb78d0d:/# mysql -u root -p homestead
      Enter password:
      Welcome to the MySQL monitor.  Commands end with ; or \g.
      Your MySQL connection id is 7
      Server version: 5.7.17 MySQL Community Server (GPL)
      
      Copyright (c) 2000, 2016, 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 databases;
      +--------------------+
      | Database           |
      +--------------------+
      | information_schema |
      | homestead          |
      | mysql              |
      | performance_schema |
      | sys                |
      +--------------------+
      5 rows in set (0.00 sec)
      

      您的卷将保留在 docker 卷中 nameoffolder_dbdata (/var/lib/docker/volumes/...)

      【讨论】:

      • 这不是我要问的,但很有趣。我想知道环境变量是否也要创建数据库。因为在docker-compose.yml图中是数据库名,为什么?
      • 我不完全理解您的回复/问题,但是是的,环境变量正在创建一个名为 homestead 的数据库。当我执行显示数据库时检查我的答案。你看到了宅基地数据库,我也在那个数据库上进行身份验证(-p)
      • 我已经有了容器。我想为容器创建数据库。你能告诉我如何为容器创建 docker-compose 文件吗?
      • 使用容器中包含数据库的图像,如 mysql 或 postgres?如果要安装自己的数据库,则必须编写 Dockerfile 并在 docker-compose 中构建映像
      【解决方案6】:

      如果我正确理解您的问题,您希望拥有一个包含特定数据库的容器。就像已经执行了带有CREATE DATABASE mydb 等的 MySQL 容器一样。如果是这样,您需要使用docker-entrypoint-initdb.dhttps://docs.docker.com/samples/library/mysql/#docker-secrets

      第一次启动官方 MySQL 容器时,会先创建一个新的数据库。然后它将执行在/docker-entrypoint-initdb.d 中找到的扩展名为.sh、.sql 和.sql.gz 的文件。所以你需要做的就是创建/docker-entrypoint-initdb.d 目录并将你的初始化脚本放在那里。

      【讨论】:

        【解决方案7】:

        此设置意味着您的数据库已经存在。否则,您必须使用初始化脚本或手动创建它。

        初始化脚本(任何 .sh.sql.sql.gz 文件)应位于 docker 容器内的 /docker-entrypoint-initdb.d/ 文件夹中。

        您所要做的就是简单地将这个初始化脚本作为一个卷添加到您的 docker-compose 文件中。

        database:
         image: mysql:latest
          volumes:
            - ./init-script.sql:/docker-entrypoint-initdb.d/init-script.sql
        
          ...
        

        您的init-script.sql 文件可能如下所示:

        CREATE DATABASE IF NOT EXISTS some_name;
        USE some_name;
        

        【讨论】:

          【解决方案8】:

          https://hub.docker.com/_/mysql/ 此处的“初始化新实例”声明将所有 .sql、.sh、.sql.gz 文件复制到“/docker-entrypoint-initdb.d”文件夹中。下面是我在很多项目中使用的 docker-compose 文件,并且在最新版本的 MySQL 中都能正常工作

          version: '3.6'
          services:   
            mysql:
                environment:
                    - MYSQL_DATABASE=root
                    - MYSQL_ROOT_PASSWORD=changeme
                    - MYSQL_USER=dbuser
                    - MYSQL_PASSWORD=changeme
                command: 
                   - --table_definition_cache=100
                   - --performance_schema=0
                   - --default-authentication-plugin=mysql_native_password
                   - --innodb_use_native_aio=0
                volumes: 
                    - ./init:/docker-entrypoint-initdb.d
                container_name: mysqldb
                image: mysql  
          

          我的 init 文件夹有一个 init.sql 文件,其中包含我需要在容器启动时重新创建的整个 sql 数据转储。

          以下命令用于将 MySQL 容器消耗的内存限制为 100 MB

                   - --table_definition_cache=100
                   - --performance_schema=0
          

          注意:如果您希望保留数据,这不会保留您的 mysql 数据,请使用以下配置

          version: '3.6'
          services:   
            mysql:
                environment:
                    - MYSQL_DATABASE=root
                    - MYSQL_ROOT_PASSWORD=changeme
                    - MYSQL_USER=dbuser
                    - MYSQL_PASSWORD=changeme
                command: 
                   - --table_definition_cache=100
                   - --performance_schema=0
                   - --default-authentication-plugin=mysql_native_password
                   - --innodb_use_native_aio=0
                volumes: 
                    - ./init:/docker-entrypoint-initdb.d
                    - ./dbdata:/var/lib/mysql
                container_name: mysqldb
                image: mysql  
          

          其中 dbdata 是您需要在主机系统上创建的文件夹。

          【讨论】:

            【解决方案9】:

            如果你想创建数据库 你的 docker-compose.yml 看起来像 如果你想使用 Dockerfile

            version: '3.1'
            
            services:
              php:
                build:
                  context: .
                  dockerfile: Dockerfile
                ports:
                  - 80:80
                volumes:
                  - ./src:/var/www/html/
              db:
                image: mysql
                command: --default-authentication-plugin=mysql_native_password
                restart: always
                environment:
                  MYSQL_ROOT_PASSWORD: example
                volumes:
                  - mysql-data:/var/lib/mysql
            
              adminer:
                image: adminer
                restart: always
                ports:
                  - 8080:8080
            volumes:
              mysql-data:
            

            你的 docker-compose.yml 看起来像 如果你想使用你的镜像而不是 Dockerfile

            version: '3.1'   
            
            services:
              php:
                image: php:7.4-apache
                ports:
                  - 80:80
                volumes:
                  - ./src:/var/www/html/
              db:
                image: mysql
                command: --default-authentication-plugin=mysql_native_password
                restart: always
                environment:
                  MYSQL_ROOT_PASSWORD: example
                volumes:
                  - mysql-data:/var/lib/mysql
            
              adminer:
                image: adminer
                restart: always
                ports:
                  - 8080:8080
            volumes:
            

            如果你想存储或保存mysql的数据,那么 一定要记得在你的 docker-compose.yml 中添加两行

            volumes:
              - mysql-data:/var/lib/mysql
            

            volumes:
              mysql-data:
            

            之后使用这个命令

            docker-compose up -d
            

            现在您的数据将永久保存,即使使用此命令也不会被删除

            docker-compose down
            

            额外:- 但如果你想删除所有数据,那么你将使用

            docker-compose down -v
            

            【讨论】:

              猜你喜欢
              • 2022-01-25
              • 2020-06-05
              • 2021-03-13
              • 2022-11-18
              • 2021-03-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多