小编典典

如何在Docker Compose中运行一次命令

go

因此,我正在研究一个docker compose文件来部署Go Web服务器。我的服务器使用mongo,因此我在docker
compose中添加了数据量容器和mongo服务。然后,我编写了一个Dockerfile来构建我的Go项目,并最终运行它。

但是,还必须执行另一步骤。编译完项目后,我必须运行以下命令: ./my-project -setup

这将向数据库添加一些必要的信息,并且该信息 仅需要添加一次
。但是,我无法在构建过程中在Dockerfile上添加此步骤,因为mongo必须已经启动。

那么,我该如何实现呢?即使重新启动服务器然后再次运行,docker-compose up我也不想再次执行此命令。

我想我对Docker有一些了解,因为我实际上并不了解有关数据卷容器的所有信息(它们只是 停止
了装载卷的容器吗?)。另外,如果我重新启动服务器,然后运行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

这是我的Dockerfile,用于构建我的项目映像:

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

阅读 792

收藏
2020-07-02

共1个答案

小编典典

我建议在您的容器中添加一个入口点脚本。在此entrypoint-script中,您可以检查数据库是否已初始化,如果尚未初始化,请执行所需的步骤。

正如您在问题中注意到的那样,不应理会服务/容器的启动顺序,因此有可能在数据库容器 之前 启动了应用程序容器,因此脚本应该考虑到这一点。

例如,看一下官方的WordPress图像,该图像在入口点脚本中执行数据库的一次性初始化。该脚本尝试连接到数据库(如果无法联系数据库,则重试),然后检查是否需要初始化。https://github.com/docker-
library/wordpress/blob/df190dc9c5752fd09317d836bd2bdcd09ee379a5/apache/docker-
entrypoint.sh#L146-L171

注意

我注意到您创建了一个“仅数据容器”来附加您的卷。从Docker 1.9开始,Docker具有卷管理功能,包括命名卷。因此,您不再需要使用“仅数据”容器。

您可以从撰写文件中删除仅数据容器,然后将mongo服务更改为如下所示;

  mongo:
    image: mongo:latest
    volumes:
      - mongodata:/data/db
    ports:
      - "28001:27017"
    command: --smallfiles --rest --auth

这应该创建一个新卷,mongodata如果它不存在则命名,或者重新使用具有该名称的现有卷。您可以列出所有使用docker volume ls的卷,docker volume rm <some-volume>如果不再需要它可以删除一个卷

2020-07-02