我正在编写一个Docker compose文件来部署我的Go Web服务器,我的服务器使用mongo,所以我在docker compose中添加了一个数据卷容器和mongo服务,然后我编写了一个Dockerfile来构建我的Go项目,最后运行它。
但是,还有一个步骤必须要做,一旦我的项目已经编译好了,我必须运行下面的命令:第一个月
这将添加一些必要的信息到数据库中,并且这些信息只需要添加一次。但是我不能在Dockerfile中添加这一步(在构建过程中),因为mongo必须已经启动。
那么,我如何才能做到这一点呢?即使我重新启动服务器,然后再次运行docker-compose up
,我也不希望这个命令再次执行。
我想我错过了一些Docker的理解,因为我实际上并不了解关于数据卷容器的一切(它们只是挂载卷的 stopped 容器吗?)。另外,如果我重新启动服务器,然后运行docker-compose up
,哪些命令将运行?它是否只是启动现在用给定CMD停止的同一个容器?
无论如何,这里是我的docker-compose.yml:
version: '2'
services:
mongodata:
image: mongo:latest
volumes:
- /data/db
command: --break-mongo
mongo:
image: mongo:latest
volumes_from:
- mongodata
ports:
- "28001:27017"
command: --smallfiles --rest --auth
my_project:
build: .
ports:
- "6060:8080"
depends_on:
- mongo
- mongodata
links:
- mongo
下面是我的Docker文件,用于构建我的项目映像:
FROM golang
ADD . /go/src/my_project
RUN cd /go/src/my_project && go get
RUN go install my_project
RUN my_project -setup
ENTRYPOINT /go/bin/my_project
EXPOSE 8080
4条答案
按热度按时间lnlaulya1#
我建议在容器中添加一个入口点脚本;在这个入口点脚本中,您可以检查数据库是否已经初始化,如果没有,则执行所需的步骤。
正如您在问题中所注意到的,服务/容器的启动顺序不应被视为理所当然,因此有可能您的应用程序容器在数据库容器之前启动,因此脚本应考虑到这一点。
As an example, have a look at the official WordPress image, which performs a one-time initialization of the database in it's entrypoint-script. The script attempts to connect to the database (and retries if the database cannot be contacted (yet)), and checks if initialization is needed; https://github.com/docker-library/wordpress/blob/df190dc9c5752fd09317d836bd2bdcd09ee379a5/apache/docker-entrypoint.sh#L146-L171
我注意到你创建了一个"仅限数据的容器"来连接你的卷,从docker 1.9开始,docker就有了卷管理,包括命名卷,正因为如此,你不再需要使用"仅限数据的"容器。
您可以从您的组合文件中删除纯数据容器,并将您的mongo服务更改为如下所示;
这将创建一个名为
mongodata
的新卷(如果该卷不存在),或者重新使用具有该名称的现有卷。您可以使用docker volume ls
列出所有卷,如果不再需要使用docker volume rm <some-volume>
,则删除该卷uajslkp62#
您可以尝试使用
ONBUILD
指令:ONBUILD
指令将向映像添加一个触发器指令,该触发器指令将在以后映像用作另一个生成的基础时执行。该触发器将在下游生成的上下文中执行,就像它已在下游Dockerfile
中紧接着FROM
指令插入一样。任何构建指令都可以注册为触发器。
如果您要构建的映像将用作构建其他映像的基础,例如应用程序构建环境或可以使用用户特定配置自定义的守护进程,则此功能非常有用。
例如,如果您的映像是一个可重用的Python应用程序构建器,则需要将应用程序源代码添加到特定目录中,并且可能需要在此之后调用构建脚本。您现在不能调用
ADD
和RUN
,因为您还没有访问应用程序源代码的权限。您可以简单地为应用程序开发人员提供一个样板文件Dockerfile
,以便复制粘贴到他们的应用程序中,但这样做效率低下、容易出错并且难以更新,因为它与特定于应用程序的代码混合在一起。解决方案是使用
ONBUILD
注册高级指令,以便在下一个构建阶段运行。下面是它的工作原理:
1.当遇到
ONBUILD
指令时,构建器会向正在构建的映像的元数据添加一个触发器。该指令不会影响当前构建。1.在构建结束时,所有触发器的列表存储在映像清单中的键
OnBuild
下,可以使用docker inspect
命令检查它们。1.稍后,可以使用
FROM
指令将该映像用作新构建的基础。作为处理FROM
指令的一部分,下游构建器查找ONBUILD
触发器,并按照注册它们的顺序执行它们。如果任何触发器失败,FROM
指令被中止,这又导致构建失败。如果所有触发成功,则FROM
指令完成,并且构建照常继续。1.触发器在执行后会从最终映像中清除。换句话说,它们不会被"孙子"构建继承。
qq24tv8q3#
您的应用程序需要一些初始状态才能工作。这意味着您应该:
1.检查所需状态是否已存在
1.取决于第一步结果初始化状态
您可以编写程序来检查当前数据库状态(这里我将使用bash脚本,但它可以是任何其他语言程序):
在我的例子中,如果脚本将返回0(成功退出状态),则将调用
setup
命令。lymnna714#
在docker-compose中,您可以定义:
重新启动:否
只运行容器一次,这对于数据库迁移容器很有用。