web-dev-qa-db-ja.com

Docker作成でコマンドを1回実行する方法

そこで、Go Webサーバーをデプロイするためにdocker composeファイルに取り組んでいます。私のサーバーはmongoを使用しているため、データボリュームコンテナーとmongoサービスをdocker composeに追加しました。次に、Goプロジェクトをビルドして最終的に実行するためにDockerfileを作成しました。

ただし、実行する必要がある別の手順があります。プロジェクトをコンパイルしたら、次のコマンドを実行する必要があります:./my-project -setup

これにより、必要な情報がデータベースに追加され、その情報が一度だけ追加する必要がありますになります。ただし、mongoは既に起動している必要があるため、この手順を(ビルドプロセスで)Dockerfileに追加することはできません。

それで、どうすればこれを達成できますか?サーバーを再起動してから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

そして、ここに私のプロジェクトイメージをビルドするための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
16
Ivan

コンテナにentrypoint-scriptを追加することをお勧めします。このエントリポイントスクリプトでは、データベースが初期化されているかどうかを確認できます。初期化されていない場合は、必要な手順を実行します。

あなたの質問で気づいたように、サービス/コンテナが開始される順序は当然とみなされるべきではないので、アプリケーションコンテナが開始される可能性がありますbeforeデータベースコンテナ、それでスクリプトはそれを取り入れるべきですアカウント。

例として、公式のWordPressイメージをご覧ください。このイメージは、entrypoint-scriptでデータベースの1回限りの初期化を実行します。スクリプトは、データベースへの接続を試行します。データベースに接続できません(まだ))、初期化が必要かどうかを確認します; https://github.com/docker-library/wordpress/blob/df190dc9c5752fd09317d836bd2bdcd09ee379a5/Apache/docker-entrypoint.sh#L146-L171

[〜#〜] note [〜#〜]

ボリュームをアタッチするための「データ専用コンテナー」を作成しました。 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>でボリュームを削除できます

7
thaJeztah

ONBUILD命令 を使用してみてください:

ONBUILD命令は、イメージが別のビルドのベースとして使用されるときに、後で実行されるトリガー命令をイメージに追加します。トリガーは、ダウンストリームFROMDockerfile命令の直後に挿入されたかのように、ダウンストリームビルドのコンテキストで実行されます。

任意のビルド命令をトリガーとして登録できます。

これは、他のイメージをビルドするためのベースとして使用されるイメージをビルドする場合に便利です。たとえば、ユーザー固有の構成でカスタマイズできるアプリケーションビルド環境やデーモンです。

たとえば、イメージが再利用可能なPythonアプリケーションビルダーの場合、特定のディレクトリにアプリケーションソースコードを追加する必要があり、ビルドスクリプトの呼び出しが必要になる場合がありますafterそれ。ADDRUNを呼び出すことはできません、まだアプリケーションソースにアクセスできないためですコードを作成し、アプリケーションのビルドごとに異なります。アプリケーション開発者にボイラープレートDockerfileを提供するだけでコピーしてアプリケーションに貼り付けることができますが、それは非効率的でエラーが発生しやすく、更新が難しいためですアプリケーション固有のコード。

解決策は、ONBUILDを使用して、次のビルド段階で後で実行する事前指示を登録することです。

仕組みは次のとおりです。

  1. ONBUILD命令が検出されると、ビルダーは作成中のイメージのメタデータにトリガーを追加します。それ以外の場合、命令は現在のビルドに影響しません。
  2. ビルドの最後に、すべてのトリガーのリストがイメージマニフェストのキーOnBuildの下に保存されます。それらはdocker inspectコマンドで検査できます。
  3. 後でイメージは、FROM命令を使用して、新しいビルドのベースとして使用できます。 FROM命令の処理の一環として、ダウンストリームビルダーはONBUILDトリガーを探し、それらが登録されたのと同じ順序で実行します。トリガーのいずれかが失敗すると、FROM命令が中止され、ビルドが失敗します。すべてのトリガーが成功すると、FROM命令が完了し、ビルドは通常どおり続行されます。
  4. トリガーは、実行後に最終画像から消去されます。言い換えれば、それらは「孫」ビルドによって継承されません。
3
Petr Shevtsov

アプリケーションを機能させるには、初期状態が必要です。それはあなたがすべきことを意味します:

  1. 必要な状態が既に存在するかどうかを確認してください
  2. 最初のステップの結果の初期化状態に依存するかどうか

現在のデータベースの状態をチェックするプログラムを作成できます(ここではbashスクリプトを使用しますが、他のすべての言語プログラムでもかまいません)。

RUN if $(./check.sh); then my_project -setup; fi

私の場合、スクリプトが0(成功終了ステータス)を返すと、setupコマンドが呼び出されます。

0
Cortwave