在Dockerfile中设置MySQL并导入转储
我试图为我的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
但是我一直得到这个错误:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)
有关如何在Dockerfile构build过程中设置数据库创build和转储导入的任何想法?
Dockerfile
每个RUN
指令都在不同的层中执行(如RUN
文档中所述)。
在你的Dockerfile
,你有三条RUN
指令。 问题是MySQL服务器只在第一个启动。 在其他的,没有MySQL正在运行,这就是为什么你的连接错误与mysql
客户端。
要解决这个问题,你有两个解决scheme。
解决scheme1:使用单线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
解决scheme2:使用脚本
创build一个可执行的脚本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
将这些行添加到您的Dockerfile
:
ADD init_db.sh /tmp/init_db.sh RUN /tmp/init_db.sh
官方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
在这里,我有docker docker/data
下的data-dump.sql,它和docker-compose运行的文件夹相关。 我将这个sql文件/docker-entrypoint-initdb.d
到容器上的这个目录/docker-entrypoint-initdb.d
。
如果你有兴趣看看它是如何工作的,可以看一下他们在GitHub中的docker-entrypoint.sh
。 他们已经添加了这个块来允许导入数据
echo for f in /docker-entrypoint-initdb.d/*; do case "$f" in *.sh) echo "$0: running $f"; . "$f" ;; *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;; *) echo "$0: ignoring $f" ;; esac echo done
另外需要注意的是,如果你希望数据在mysql容器被停止和删除之后仍然被保存,你需要有一个单独的数据容器,就像你在docker-compose.yml中看到的那样。 数据容器Dockerfile的内容非常简单。
FROM n3ziniuka5/ubuntu-oracle-jdk:14.04-JDK8 VOLUME /var/lib/mysql CMD ["true"]
数据容器甚至不必处于持久性的启动状态。
我所做的是将我的SQL转储下载到“db-dump”文件夹中,然后装载它:
mysql: image: mysql:5.6 environment: MYSQL_ROOT_PASSWORD: pass ports: - 3306:3306 volumes: - ./db-dump:/docker-entrypoint-initdb.d
当我第一次运行docker-compose up
时,转储在db中被恢复。
我用docker-entrypoint-initdb.d方法(感谢@Kuhess)但是在我的情况下,我想根据我在.env文件中定义的一些参数来创build我的数据库,所以我做了这些
1)首先,我在docker root project目录下定义.env文件
MYSQL_DATABASE=my_db_name MYSQL_USER=user_test MYSQL_PASSWORD=test MYSQL_ROOT_PASSWORD=test MYSQL_PORT=3306
2)然后我定义我的docker-compose.yml文件。 所以我使用args指令来定义我的环境variables,并从.env文件中设置它们
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"
3)然后我定义一个包含Dockerfile的mysql文件夹。 所以Dockerfile是这样的
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
4)现在我使用mysqldump转储我的数据库,并把data.sql里面的MySQL文件夹
mysqldump -h <server name> -u<user> -p <db name> > data.sql
该文件只是一个正常的SQL转储文件,但我在开始时添加2行,所以文件看起来像这样
-- -- 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 ...; ... ... ...
所以发生什么事情是我用“运行sed -i's / MYSQL_DATABASE /'$ MYSQL_DATABASE'/ g'/etc/mysql/data.sql”命令来replaceMYSQL_DATABASE
占位符与我已经设置了它的数据库的名称在.env文件中。
|- docker-compose.yml |- .env |- mysql |- Dockerfile |- data.sql
现在您已经准备好构build并运行您的容器
您也可以看看docker-compose的服务:
https://docs.docker.com/compose/wordpress/#build-the-project
与此同时,MySQL可以附加到您的应用程序