私はC++で記述されたサーバーを構築していて、Dockerを docker-compose で使用してデプロイしたいと考えています。それを行う「正しい方法」は何ですか? Dockerfileからmake
を呼び出すか、手動でビルドし、サーバーにアップロードしてから、DockerfileからCOPY
バイナリをアップロードする必要がありますか?
docker-compose
を使用してビルドを自動化するのが難しく、結局すべてにdocker build
を使用することになりました。
構築のための3つの層
実行→開発→ビルド
次に、ビルド出力を「デプロイ」イメージにコピーします。
実行→展開
遊ぶ4つのレイヤー:
FROM <projname>:run
FROM <projname>:develop
FROM <projname>:run
RUN
またはENTRYPOINT
は、アプリケーションの起動に使用されますフォルダー構造は次のようになります。
.
├── run
│ └── Dockerfile
├── develop
│ └── Dockerfile
├── build
│ ├── Dockerfile
│ └── removeOldImages.sh
└── deploy
├── Dockerfile
└── pushImage.sh
ビルドサーバーを設定することは、実行することを意味します:
docker build -f run -t <projName>:run
docker build -f develop -t <projName>:develop
ビルドを行うたびに、これが発生します。
# Execute the build
docker build -f build -t <projName>:build
# Install build outputs
docker build -f deploy -t <projName>:version
# If successful, Push deploy image to dockerhub
docker tag <projName>:<version> <projName>:latest
docker Push <projName>:<version>
docker Push <projName>:latest
プロジェクトをビルド/実行/インストールする方法についてのドキュメントとしてDockerfilesを参照するようにします。
ビルドが失敗し、出力が調査に不十分な場合、/bin/bash
で<projname>:build
を実行して、何が問題かを確認することができます。
私はこのアイデアを中心に GitHubリポジトリ をまとめました。 C++ではうまく機能しますが、おそらく何にでも使用できます。
私はこの機能を調査していませんが、@ TaylorEdmistonは私のパターンは multi-stage builds と非常に似ていることを指摘しました。これは、同じことを実現するためのよりエレガントな(そしてドキュメント化された)方法のように見えます。
私の推奨は、コンテナ自体で完全に開発、構築、テストすることです。これにより、開発者の環境が本番環境と同じであるというDockerの哲学が保証されます。Dockerを使用するMacOS上の最新の開発者用ワークステーションを参照してください。
特に、通常は共有ライブラリ/オブジェクトファイルとの依存関係があるC++アプリケーションの場合。
DockerでC++アプリケーションを開発、テスト、デプロイするための標準化された開発プロセスはまだ存在していないと思います。
あなたの質問に答えるために、現時点での私たちのやり方は、コンテナーを開発環境として扱い、次のような一連のプラクティスをチームに適用することです。
docker diff
変更は期待どおりです。2017年以降にこの質問にアクセスする方は、 マルチアンサーDockerビルド の使用について the answer by fuglede を参照してください。私の回答(下記)は、それが利用可能になるずっと前の2015年からのものです。
私が行う方法は、コンテナーの外でビルドを実行し、ビルドの出力(バイナリーと必要なライブラリー)のみをコンテナーにコピーすることです。次に、コンテナーをコンテナーレジストリにアップロードし(たとえば、ホストされているものを使用するか、独自のコンテナーを実行します)、そのレジストリから運用マシンにプルします。したがって、フローは次のようになります。
プロダクションデプロイメントの前にテストすることが重要であるため、本番環境にデプロイするのとまったく同じものをテストしたいので、Dockerイメージをビルドした後に何らかの方法で抽出または変更したくありません。
私は、製品にデプロイする予定のコンテナーのビルドの内側を実行しません。コンテナーには、あらゆる種類の追加のアーティファクト(一時的なビルドなど)が含まれるためです。出力、ツールなど)。本番環境では不要であり、デプロイに使用しないものでコンテナイメージを不必要に拡張します。
他の回答で提示された解決策、特にコメントへのMisha Brukmanの提案 この回答 1つのDockerfileを開発用と1つを本番用に使用することについて-は、当時は慣用的と見なされます質問が書かれました、彼らが解決しようとしている問題-特に、開発と本番環境で同じコンテナ環境を使用しながら、イメージサイズを減らすためにビルド環境をクリーンアップする問題-に注意してくださいDocker 17.05で導入されたマルチステージビルドによって効果的に解決されました。
ここでのアイデアは、Dockerfileを2つの部分に分割することです。1つは完全なDebianベースイメージなど、お気に入りの開発環境に基づいており、最後にデプロイするバイナリの作成に関係しています。日、そしてアルパインのような最小限の環境でビルドされたバイナリを実行する別の日。
このようにして、コメントの1つでブルースキンが示唆しているように、開発環境と本番環境の間の不一致の可能性を回避しながら、プロダクションイメージが開発ツールで汚染されないようにします。
ドキュメントには、次のGoアプリケーションのマルチステージビルドの例が示されています。これは、C++開発環境に採用されます(1つは、アルパインが musl を使用しているため、注意が必要な場合があります)。開発環境でのリンク)。
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM Alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]