设置 MySQL 并在 Dockerfile 中导入转储

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25920029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 13:03:37  来源:igfitidea点击:

Setting up MySQL and importing dump within Dockerfile

mysqldocker

提问by vinnylinux

I'm trying to setup a Dockerfile for my LAMP project, but i'm having a few problems when starting MySQL. I have the folowing lines on my Dockerfile:

我正在尝试为我的 LAMP 项目设置一个 Dockerfile,但是在启动 MySQL 时遇到了一些问题。我的 Dockerfile 上有以下几行:

VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql

But I keep getting this error:

但我不断收到此错误:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

Any ideas on how to setup database creation and dump import during a Dockerfile build?

关于如何在 Dockerfile 构建期间设置数据库创建和转储导入的任何想法?

采纳答案by Kuhess

Each RUNinstruction in a Dockerfileis executed in a different layer (as explained in the documentation of RUN).

a 中的每条RUN指令都在Dockerfile不同的层中执行(如 的文档中所述RUN)。

In your Dockerfile, you have three RUNinstructions. The problem is that MySQL server is only started in the first. In the others, no MySQL are running, that is why you get your connection error with mysqlclient.

在您的 中Dockerfile,您有三个RUN指令。问题是 MySQL 服务器只在第一次启动。在其他情况下,没有 MySQL 正在运行,这就是您与mysql客户端的连接错误的原因。

To solve this problem you have 2 solutions.

要解决此问题,您有 2 个解决方案。

Solution 1: use a one-line RUN

解决方案1:使用单行 RUN

RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && \
  sleep 5 && \
  mysql -u root -e "CREATE DATABASE mydb" && \
  mysql -u root mydb < /tmp/dump.sql

Solution 2: use a script

解决方案2:使用脚本

Create an executable script init_db.sh:

创建一个可执行脚本init_db.sh

#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql

Add these lines to your Dockerfile:

将这些行添加到您的Dockerfile

ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh

回答by Rajiv

The latest version of the official mysql docker imageallows you to import data on startup. Here is my docker-compose.yml

最新版本的官方mysql docker 镜像允许您在启动时导入数据。这是我的 docker-compose.yml

data:
  build: docker/data/.
mysql:
  image: mysql
  ports:
    - "3307:3306"
  environment:
    MYSQL_ROOT_PASSWORD: 1234
  volumes:
    - ./docker/data:/docker-entrypoint-initdb.d
  volumes_from:
    - data

Here, I have my data-dump.sql under docker/datawhich is relative to the folder the docker-compose is running from. I am mounting that sql file into this directory /docker-entrypoint-initdb.don the container.

在这里,我的 data-dump.sql 与运行 docker docker/data-compose 的文件夹相关。我正在将该 sql 文件安装到/docker-entrypoint-initdb.d容器上的这个目录中。

If you are interested to see how this works, have a look at their docker-entrypoint.shin GitHub. They have added this block to allow importing data

如果您有兴趣了解这是如何工作的,请查看他们docker-entrypoint.sh在 GitHub 中的内容。他们添加了此块以允许导入数据

    echo
    for f in /docker-entrypoint-initdb.d/*; do
        case "$f" in
            *.sh)  echo "
FROM n3ziniuka5/ubuntu-oracle-jdk:14.04-JDK8

VOLUME /var/lib/mysql

CMD ["true"]
: running $f"; . "$f" ;; *.sql) echo "
mysql:
 image: mysql:5.6
 environment:
   MYSQL_ROOT_PASSWORD: pass
 ports:
   - 3306:3306
 volumes:
   - ./db-dump:/docker-entrypoint-initdb.d
: running $f"; "${mysql[@]}" < "$f" && echo ;; *) echo "
MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306
: ignoring $f" ;; esac echo done

An additional note, if you want the data to be persisted even after the mysql container is stopped and removed, you need to have a separate data container as you see in the docker-compose.yml. The contents of the data container Dockerfile are very simple.

另外要注意的是,如果您希望即使在 mysql 容器停止和删除后仍然保留数据,您需要有一个单独的数据容器,如 docker-compose.yml 中所示。数据容器 Dockerfile 的内容非常简单。

version: '2'
services:
### MySQL Container
    mysql:
        build:
            context: ./mysql
            args:
                - MYSQL_DATABASE=${MYSQL_DATABASE}
                - MYSQL_USER=${MYSQL_USER}
                - MYSQL_PASSWORD=${MYSQL_PASSWORD}
                - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
        ports:
            - "${MYSQL_PORT}:3306"

The data container doesn't even have to be in start state for persistence.

数据容器甚至不必处于启动状态以实现持久性。

回答by Petru

What I did was download my sql dump in a "db-dump" folder, and mounted it:

我所做的是将我的 sql 转储下载到“db-dump”文件夹中,并安装它:

FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/

ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD

ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD

ADD data.sql /etc/mysql/data.sql
RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d

EXPOSE 3306

When I run docker-compose upfor the first time, the dump is restored in the db.

当我docker-compose up第一次运行时,转储在数据库中恢复。

回答by Saman Shafigh

I used docker-entrypoint-initdb.d approach (Thanks to @Kuhess) But in my case I want to create my DB based on some parameters I defined in .env file so I did these

我使用了 docker-entrypoint-initdb.d 方法(感谢@Kuhess)但在我的情况下,我想根据我在 .env 文件中定义的一些参数创建我的数据库,所以我做了这些

1)First I define .env file something like this in my docker root project directory

1)首先,我在我的 docker 根项目目录中定义了类似这样的 .env 文件

mysqldump -h <server name> -u<user> -p <db name> > data.sql

2)Then I define my docker-compose.yml file. So I used the args directive to define my environment variables and I set them from .env file

2)然后我定义我的 docker-compose.yml 文件。所以我使用 args 指令来定义我的环境变量,并从 .env 文件中设置它们

--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;

-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...

3)Then I define a mysql folder that includes a Dockerfile. So the Dockerfile is this

3)然后我定义了一个包含 Dockerfile 的 mysql 文件夹。所以 Dockerfile 是这样的

|- docker-compose.yml
|- .env
|- mysql
     |- Dockerfile
     |- data.sql

4)Now I use mysqldump to dump my db and put the data.sql inside mysql folder

4)现在我使用 mysqldump 转储我的数据库并将 data.sql 放在 mysql 文件夹中

mysql:
  image: mysql:5.6
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_USER: theusername
    MYSQL_PASSWORD: thepw
    MYSQL_DATABASE: mydb
  volumes:
    - ./data:/docker-entrypoint-initdb.d

The file is just a normal sql dump file but I add 2 lines at the beginning so the file would look like this

该文件只是一个普通的 sql 转储文件,但我在开头添加了 2 行,因此文件看起来像这样

##代码##

So what happening is that I used "RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql" command to replace the MYSQL_DATABASEplaceholder with the name of my DB that I have set it in .env file.

所以发生的事情是我使用“RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql”命令将MYSQL_DATABASE占位符替换为我设置的数据库名称.env 文件。

##代码##

Now you are ready to build and run your container

现在您已准备好构建和运行您的容器

回答by rynop

Here is a working version using v3of docker-compose.yml. The key is the volumesdirective:

下面是使用一个工作版本v3docker-compose.yml。关键是指令:

##代码##

In the directory that I have my docker-compose.ymlI have a datadir that contains .sqldump files. This is nice because you can have a .sqldump file per table.

docker-compose.yml我拥有的data目录中,我有一个包含.sql转储文件的目录。这很好,因为您可以为.sql每个表创建一个转储文件。

I simply run docker-compose upand I'm good to go. Data automatically persists between stops. If you want remove the data and "suck in" new .sqlfiles run docker-compose downthen docker-compose up.

我只是跑docker-compose up,我很高兴去。数据在停止之间自动保留。如果你想删除的数据,并“吸入”新的.sql文件上运行docker-compose down,然后docker-compose up

If anyone knows how to get the mysqldocker to re-process files in /docker-entrypoint-initdb.dwithout removing the volume, please leave a comment and I will update this answer.

如果有人知道如何mysql/docker-entrypoint-initdb.d不删除卷的情况下让docker 重新处理文件,请发表评论,我将更新此答案。