一个默认命令
我们将学习根据我们的需求修改 Dockerfile。
修改 Dockerfile
目前,每次我们想要在容器中启动 Rails 服务器时,都必须显式指定命令 bin/rails s -b 0.0.0.0 作为 docker run 命令的一部分。这是一个问题,因为我们的自定义镜像的主要目的就是启动 Rails 服务器。如果能将如何启动 Rails 服务器的知识嵌入到镜像本身中会更好。
CMD 指令
我们可以通过向 Dockerfile 添加一条新指令来实现这一点。CMD 指令(“命令”)指定了从镜像启动容器时默认要运行的命令。让我们在 Dockerfile 中使用它,以默认方式启动 Rails 服务器:
1CMD ["bin/rails", "s", "-b", "0.0.0.0"]
观察这行新代码,你可能会注意到用于指定命令的奇怪数组语法。这种形式被称为 Exec 形式,它确保我们的 Rails 服务器作为容器中的第一个进程启动,并正确接收 Unix 信号(例如终止信号)。这是推荐的形式,也是最常用的。
CMD 指令的另一种形式很少使用,它省略了数组语法,直接写出命令:
1CMD bin/rails s -b 0.0.0.0
这被称为 Shell 形式,因为 Docker 通过命令 shell 执行该命令,前面加上 /bin/sh -c,因此在我们的例子中,它运行的是 /bin/sh -c bin/rails s -b 0.0.0.0。问题是,/bin/sh -c 而不是 Rails 服务器,是容器内的第一个进程;由于 /bin/sh -c 不会将信号传递给子进程,这会导致尝试终止服务器时出现问题。通常情况下,你可以完全避免使用这种形式。
运行修改后的 Dockerfile
现在,让我们使用新的 CMD 指令重新构建我们的镜像。使用此 Dockerfile 构建的新镜像将帮助我们省略 bin/rails s -b 0.0.0.0 来启动 Rails 服务器。
需要注意的是,CMD 指令仅提供默认命令。在执行 docker run 命令时,你可以指定不同的命令。
例如,要列出我们的 Rake 任务,我们将运行以下命令。在按下 Ctrl+C 后,你可以在终端中尝试运行它。
1$ docker run --rm railsapp bin/rails -T
🍀 练习
请尝试完成以下操作:
-
编辑 Dockerfile,添加
CMD指令。 -
点击 Run 按钮。
-
构建名为 railsapp 的
image。 -
启动 Rails 服务器,省略
bin/rails s -b 0.0.0.0。 -
点击 URL 查看默认的 Rails 页面。
-
退出 bash shell。
-
运行 Rake 任务。
提醒: 镜像构建需要时间(大约 10–12 分钟)。如果终端断开连接,请再次点击 Run 按钮。
No configuration found for ID: eaf9efdf4f1bbead82a9ed80a82507fe1b2282d779f5e927605f3a249bd536fb
解决方案如下:
-
添加
CMD ["bin/rails", "s", "-b", "0.0.0.0"]。 -
点击 Run 按钮。
-
通过以下命令构建名为 railsapp 的
image:1docker build -t railsapp . -
使用以下命令启动 Rails 服务器,省略
bin/rails s -b 0.0.0.0:1docker run -p 3000:3000 railsapp -
点击 URL 查看默认的 Rails 页面。
-
通过
Ctrl+C退出 bash shell。 -
通过以下命令运行 Rake 任务:
1docker run --rm railsapp bin/rails -T
解决方案:
-
添加
CMD ["bin/rails", "s", "-b", "0.0.0.0"]。 -
点击 Run 按钮。
-
通过以下命令构建名为 railsapp 的
image:1docker build -t railsapp . -
通过以下命令启动 Rails 服务器,省略
bin/rails s -b 0.0.0.0:1docker run -p 3000:3000 railsapp -
点击 URL 查看默认的 Rails 页面。
-
通过
Ctrl+C退出 bash shell。 -
通过以下命令运行 Rake 任务:
1docker run --rm railsapp bin/rails -T
注意:
--rm选项在容器运行结束后将其删除。我们在这里使用它,而不在运行 Rails 服务器时使用,是因为该容器在生成 Rake 任务输出后已达到其目的,而用于运行 Rails 服务器的容器可以重复使用。