如何在基于基础mysql / mysql-server的Docker容器中启动MySQL服务器

时间:2018-10-21 08:35:04

标签: mysql docker

我想基于mysql / mysql-server创建一个docker镜像。 我有一个应使用MySQL存储数据的应用程序(golang)。我想在docker中运行此应用

我的Docker文件看起来像

FROM mysql/mysql-server
ENV MYSQL_ROOT_PASSWORD rootpass
ENV MYSQL_DATABASE mydb
ENV MYSQL_USER dbuser
ENV MYSQL_PASSWORD dbpass

ADD myapp / # compiled colang app connecting to localhost:3306 mysql server
CMD ["myapp"]

我构建了该映像并运行它并出现错误

docker run --name mycont -it myimage
dial tcp [::1]:3306: getsockopt: connection refused

这是怎么了?

也许我必须以某种方式启动mysql服务器才能执行我的应用程序?

我的应用尝试使用用户dbuser / dbpassword和数据库mydb连接到localhost:3306上的mysql。然后将在数据库中创建一些表

1 个答案:

答案 0 :(得分:1)

嗯,有可能实现这一目标,但是这并不是一种好的做法。推荐的方法是运行两个不同的容器:一个运行mysql,另一个运行您的应用程序。除此之外,您还需要一个编排工具来运行容器。

因此,冒着被低票压的风险:-),与其直接回答您的问题并说明如何创建一个可以同时运行两个功能的容器,不如说我会展示两种容器的方法,我认为是更好的做法。

在我的示例中,我使用docker compose进行编排。如果尚未安装,则需要安装。 以下是我用来运行两个容器的docker-compose.yml文件:

version: '3'
services:
  mysqlserver:
    image: mysql/mysql-server
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: "rootpass"
      MYSQL_DATABASE: "mydb"
      MYSQL_USER: "dbuser"
      MYSQL_PASSWORD: "dbpass"

  myapp:
    image: myimage
    environment:
      MYSQL_SERVER: "mysqlserver"
      MYSQL_DATABASE: "mydb"
      MYSQL_USER: "dbuser"
      MYSQL_PASSWORD: "dbpass"

该文件定义了两个服务:mysqlservermyapp,将作为单独的容器运行。这两个服务各自定义两个元素:

  • 用于创建容器的image
  • 传递到该容器的environment变量

mysqlserver服务定义了两个额外的属性:

  • command,它指定运行时传递给mysql服务的额外参数。简而言之:对于MySQL 8,--default-authentication-plugin是必需的。尝试在没有容器的情况下运行容器,最终可能会遇到一些连接错误。您可以在官方的mysql docker页面上阅读有关此内容的更多信息。
  • ports,它指定哪些容器端口暴露在外部

现在,让我们定义您的应用图片。我不会说golang,但是我使用Linux shell脚本编写了一个简单的示例。

myapp代码如下:

#!/bin/sh

echo ">> Waiting for $MYSQL_SERVER to start"
while ! `nc -z $MYSQL_SERVER 3306`; do sleep 3; done
echo ">> $MYSQL_SERVER has started"

mysql --host=$MYSQL_SERVER --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE<<EOFMYSQL
drop table if exists test;
create table test(id int, name varchar(20));
insert into test values (5, 'a'), (12, 'b');
select * from test;
EOFMYSQL

该应用将首先在while循环中运行nc命令,每3秒检查mysql服务器的状态,并且仅在mysqlserver完全启动并接受端口3306上的连接时退出循环我们需要确保数据库服务器正在运行,然后再尝试连接它,对吧?

服务器启动后,myapp使用在docker compose文件中作为环境变量传递的凭据连接到服务器。连接后,它将运行一些sql语句(删除表,创建表,插入,选择)。 所有这些环境参数都可以用myapp的代码进行硬编码,但是我认为最好将它们传递到docker compose文件中。

用于创建Dockerfile图像的myapp如下:

FROM alpine

RUN apk add netcat-openbsd mysql-client
ADD myapp /
RUN chmod +x /myapp
CMD /myapp

我通常使用Alpine Linux作为测试基础,因为它非常轻巧。我需要运行apk add netcat-openbsd mysql-client以将ncmysql-client添加到图像中。 代替myapp shell脚本,您只需添加golang myapp文件。

现在,让我们组装所有东西。进一步执行以下步骤:

  • Dockerfilemyapp文件放在同一文件夹中并构建myapp映像:

docker image build -t myimage .

  • 运行docker以上面的docker-compose.yml文件作为输入:

docker-compose -f docker-compose.yml up

此时,两个容器都将启动。 myapp将等待mysqlserver准备就绪,然后将其连接并运行简单查询。

我不确定您对linux,shell脚本,yaml语法等的熟悉程度如何。但是我希望我能为您提供足够的详细信息,以便您理解。