【问题标题】:Docker container for SQL Server Linux keeps exitingSQL Server Linux 的 Docker 容器不断退出
【发布时间】:2017-05-21 01:16:02
【问题描述】:

我想通过在容器启动时添加一个带有一个表的简单数据库来修改 SQL Server Linux 容器的行为。

我看到此问题的 docker 映像版本是截至 2017 年 5 月 20 日的最新版本,即ctp2-1

我正在使用Docker for Windows17.05.0-ce 的最新版本。我将 MobyLinuxVM 的 RAM 增加到 6144MB,因为建议使用 4GB 以上。

重现问题的步骤

准备文件

(1) Create a local Windows folder, in my case, 

    C:\temp\docker\

(2) Add "Dockerfile" (note no file extension) with the following content.

    FROM microsoft/mssql-server-linux:latest
    COPY ./custom /tmp
    RUN chmod +x /tmp/entrypoint.sh \
        && chmod +x /tmp/createdb.sh
    CMD /bin/bash /tmp/entrypoint.sh

(3) Add a subfolder "custom"

    C:\temp\docker\custom\

(4) Add 3 files to "custom" subfolder with following content.

   (A) entrypoint.sh
    /opt/mssql/bin/sqlservr & /tmp/createdb.sh

   (B) createdb.sh
    sleep 30s
    /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P '!StrongPass45' -d master -i /tmp/createdb.sql

   (C) createdb.sql
    CREATE DATABASE DemoData;
    GO
    USE DemoData;
    GO
    CREATE TABLE Products (ID int, ProductName nvarchar(max));
    GO

运行 Docker 命令(您将在此处的最后一步看到问题)

(1) Open PowerShell and cd to folder in step (1) above, in my case

    cd C:\temp\docker

(2) Run docker build command

    docker build .

(3) After image is built, run the following command and remember the first 3 letters of your image id, in my case "e65"

    docker images

    [![enter image description here][2]][2]

(4) Create the container with the following command (note the last 3 characters should be replaced by yours, also use the same password you used above)

    docker run -d -e SA_PASSWORD="!StrongPass45" -e ACCEPT_EULA="Y" -p 1433:1433 e65

(5) Check your container is running

    docker ps -a

  [![enter image description here][2]][2]

(6) Wait about 2 minutes and check your container status again. AT THIS POINT, THE CONTAINER WOULD HAVE EXITED.

   docker ps -a

   [![enter image description here][2]][2]

我检查了如下日志。

docker logs e65

下面附上SQL Server成功创建DemoData数据库后的日志底部。

[![enter image description here][2]][2]

IMO,日志中的问题行是这一行

Parallel redo is shutdown for database 'DemoData' with worker pool size [1].

我尝试了各种其他 SQL 语句(甚至添加自定义 MDF 和 LDF 文件并附加到它们)以向 OOB 图像添加行为。 我什至能够在容器退出前几秒钟使用 SSMS 连接到新数据库!

有人看过这个问题吗?有人可以试试吗?

【问题讨论】:

  • 您的启动命令可能正在返回,从而退出容器。如果将 -d 替换为 -it,将 /bin/bash 添加到运行命令的末尾,您将获得交互式提示并可以对 CMD 进行故障排除。
  • @user2105103 我进行了交互,得到了 bash 提示符,然后简单地运行“/tmp/entrypoint.sh”,这正是 Dockerfile 中的 CMD 应该做的。好吧,容器工作并且没有使用交互式退出。你知道会发生什么吗?
  • CMD 返回了吗?如果你把你的 createdb 注释掉,它会起作用吗?
  • @user2105103,是的,CMD 正在返回。如果我注释掉 createdb,它可以工作,但显然没有 db。所以我想问题是如何让 CMD 不返回,对吧?这很难做到吗?

标签: sql-server linux docker dockerfile


【解决方案1】:

有效的解决方案

根据我收到的反馈,很明显来自 Dockerfile 的 CMD 正在返回。以下是解决问题的完整步骤。

[如果您找到了不依赖于某个超时值的更可靠的解决方案,请告诉我,我在此解决方案中编写了代码以允许 SQL Server 在容器启动时自行引导]

准备文件

(1) 创建一个本地 Windows 文件夹,在我的例子中,

C:\temp\docker\

(2)添加“Dockerfile”(注意没有文件扩展名),内容如下。

FROM microsoft/mssql-server-linux:latest
COPY ./custom /tmp
RUN chmod +x /tmp/entrypoint.sh
CMD /bin/bash /tmp/entrypoint.sh

(3) 添加子文件夹“custom”

C:\temp\docker\custom\

(4) 将2个文件添加到“自定义”子文件夹中,如下所示。

entrypoint.sh

#!/bin/bash

set -e
run_cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P HdkPKD57%@6876^ -l 30 -d master -i /tmp/createdb.sql"

>&2 echo "Allowing 30 seconds for SQL Server to bootstrap, then creating database.."
until $run_cmd & /opt/mssql/bin/sqlservr; do
>&2 echo "This should not be executing!"
done

createdb.sql

CREATE DATABASE DemoData;
GO
USE DemoData;
GO
CREATE TABLE Products (ID int, ProductName nvarchar(max));
GO

运行 Docker 命令

(A) 在我的情况下,打开 PowerShell 并 cd 到上述步骤 (1) 中的文件夹

cd C:\temp\docker

(B) 运行 docker build 命令

docker build .

(C) 构建图像后,获取图像的前 3 个字符,在我的情况下为 086

docker images

(D) 使用正确的镜像 id 和正确的密码创建容器

docker run -d -e 'SA_PASSWORD=HdkPKD57%@6876^' -e 'ACCEPT_EULA=Y' -p 1433:1433 086

(E) 检查您的容器是否正在运行

docker ps -a

此容器不会退出!创建了预期的数据库“DemoData”。问题解决了!

docker logs 2aa 命令(2aa 是我的容器 id,你的会不同)显示干净的构建,没有错误或警告。日志开始如下

Allowing 30 seconds for SQL Server to bootstrap, then creating database..
This is an evaluation version.  There are [173] days left in the evaluation period.
2017-05-21 17:39:50.69 Server      Setup step is copying system data file 'C:\templatedata\master.mdf' to '/var/opt/mssql/data/master.mdf'.
....

并如下结束。

2017-05-21 17:39:54.20 spid51      Starting up database 'DemoData'.
2017-05-21 17:39:54.43 spid51      Parallel redo is started for database 'DemoData' with worker pool size [1].
2017-05-21 17:39:54.44 spid51      Parallel redo is shutdown for database 'DemoData' with worker pool size [1].
2017-05-21 17:39:54.51 spid7s      Recovery is complete. This is an informational message only. No user action is required.
Changed database context to 'DemoData'.

与 SSMS 连接

我能够使用 SSMS 成功连接到该数据库,如下所示(IP 地址10.0.75.1 是包含容器的 docker 主机的地址)

重要提示

  • sqlcmd SA 密码

    sqlcmd 是用于运行dbcreate.SQL 和创建数据库DemoData 的实用程序。该实用程序在 Linux 上使用 ODBC 驱动程序,并且对如何指定开关值很敏感,尤其是密码 -P

    为避免与登录相关的问题found hereexplained here,请仔细选择您的强密码,并在-P 下的entrypoint.sh 中指定它,不要用double quotessingle quotes[] 包装。请参阅上面的(4)

    此外,此密码必须与您传递给容器的docker run 环境变量相匹配。请参阅上面的(D) 以避免密码不匹配。

    详细documentation on sqlcmd is here

  • sqlcmd 登录超时

    注意我如何使用-l 开关在entrypoint.sh 文件中为sqlcmd 指定30 seconds 的登录超时。这是我避免 CMD 返回(这使容器退出)的解决方案的症结所在。此超时时间足够长,足以让 SQL Server 启动。

【讨论】:

  • #1 - 更改您的 sa 密码 ;) #2 - 另一种方法是让容器正常启动,然后 docker exec 之后执行 createdb 命令。
  • @user2105103, #2 可以工作,但在我的情况下,我正在自动化构建机器上的所有内容并将图像推送到注册表。拉出者只需要docker pull <image>,数据库就会在那里。这使拉取者无需了解创建数据库的细节。我有使用Entity Framework Code First Migration 创建数据库并作为图像推送到注册表的自动化场景。然后,另一个开发人员将 docker-compose 一个新的应用程序,其中已经处理了 db 部分。不知道#1 - Change your sa password 是什么意思。
  • 我一直在尝试遵循这一点,但在 .sql 脚本似乎从未运行过的地方感到困惑。有没有可能遗漏的步骤?我已经验证如果我从 bash 内部运行它,它工作得很好,但就像你喜欢一个完全自动化的解决方案一样
猜你喜欢
  • 2020-09-09
  • 2022-12-22
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 2017-04-21
  • 2020-07-16
  • 1970-01-01
相关资源
最近更新 更多