Dockerを利用するための具体的な方法とデリバリープロセス

**Docker**は継続的なデリバリーの実施方法を刷新しました。**Docker**を使うと、アプリケーションをすべての依存関係を持ったスタンダーにパッケージ化することができます。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/changing-the-way-of-continuous-delivery-with-docker-part-2_194385)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#序章
Dockerは、継続的なデリバリーの実施方法を刷新したサービスです。Dockerを利用することで、ソフトウェア開発のための標準化された単位にアプリケーションの依存関係をすべてパッケージ化することができ、環境に関係なく常に同じ動作を保証してくれます。本シリーズの前編では、Dockerを使用するための概要、課題、環境とビルド要件について説明しました。今回の記事では、Dockerを利用するための具体的な方法を、デリバリプロセスと合わせて探っていきます。

#Dockerの使い方
###ステップ1：Dockerランタイム環境のインストール
Dockerランタイム環境には1つだけ制限があり、それはLinuxの動作カーネルがバージョン3.10以上である必要があるということです。Dockerでは、[Docker Toolbox](https://www.docker.com/products/docker-desktop?spm=a2c65.11461447.0.0.19d92bf4khfvK4)を使ってマシンにDocker環境をインストールして設定する便利な方法を提供しています。このインストーラーを利用することで、基盤となるOSに関係なく簡単にDockerをインストールすることができます。また、Alibaba Cloudの[ECS（Elastic Computing Service）](https://www.alibabacloud.com/ja/product/ecs)サーバをはじめ、さまざまなクラウドサーバに対応しています。

###ステップ2：Dockerfileを使ってアプリケーション環境を記述する
- 方法1.
O&M担当者は、もともと環境構築に必要な項目をすべてリストアップし、Dockerfileで記述する必要があります。Dockerfileは開発言語ではなく、定義された記述言語でしかありません。記述言語を作成するには、FROM命令とFROMに環境を記述する必要があります。これが定義されていると、コマンド実行のための実行、環境変数としてのイベント、追加、公開、cmdコマンドの実行など、役割と責任が割り当てられたタスクを実行することができます。

- 方法2.
標準的なJava環境が確立されたら、jarを適用して直接利用することができます。

サービスがマイクロサービスに分解されている場合（各サービスはウォーパッケージではなくjarである）、すべてのマイクロサービスは共通のDockerイメージを共有する必要があります。多くの言語にはAPI機能があり、依存関係を必要とせず、その言語の実行環境を必要とする場合が多いです。

様々な環境に対応したDockerイメージは、多くの公式サイトで公開されています。FROM公式サイトのイメージにjarを適用することで、直接利用することができます。また、オープンソースソフトウェアの中には、Gitlabのようにダウンロードした後に直接実行できるものもあります。Dockerの技術を使えば、複数のオープンソースのツールシステムを構築することも格段に簡単になります。

###ステップ3：Dockerを使ってコンパイル/単体テスト環境を構築する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/d0969a4b-f427-038b-740d-78b58e8a6643.png)


- アプリケーションのコンパイルとDocker環境の分離
アプリケーションとDocker環境を一緒にコンパイルする場合、アプリケーションコードをDocker環境にコピーする必要があります。しかし、Docker環境を構築する過程で、Docker環境内にアプリケーションコードが構築されている場合、それらは削除されてしまいます。Dockerの階層構造（コンテキスト全体で大文字と小文字が調和している）を考えると、jarをビルドするためにDockerファイルにコピーされた.javaは、jarがビルドされた後に削除されます。ソースコードへのアクセスは単に.javaを経由しているだけなので。これに加えて、本番環境でDockerコンテナが向こうで実行された場合、コードは望ましくありません。

- コンパイル環境とテスト環境の分離
最小限のDockerイメージの原則(必要なものだけをインストールする)に基づいて、Java(大文字と小文字を調和させた)+NodeJSの実行環境は、本番環境の実行開始後にpingが必要なく、O&M時のデバッグに必要なものだけをインストールします。コンパイルの方が依存度は高いかもしれませんが、本番環境の実行は依存度を必要としません。そのため、環境を分けて、Dockerを利用してコンパイル環境も作成することをお勧めします。

コンパイル環境はビルドのための環境であり、テスト環境は実行のための環境である。プロシージャを構築するための環境を使用するプロセスは、この単純な原理に従っています。

コードのアップロードは、「ビルド」と呼ばれるコンテナに-vメソッドを使用して進めることができます。"ビルド "と呼ばれるコンテナでは、バイナリ依存パッケージなどのファイルをビルドするために異なる言語を使用することができます; そして、これらのファイルをDockerビルド用のDockerファイルに追加します。ビルドの2つのステップを経て、実行可能なDockerイメージをビルドすることに成功します。

ソースコード以外にも、最初のビルドのステップで作成したバイナリをDockerファイルに追加して実行します。

イメージをビルドした後は、本番を実行するためのプロダクションスクリプトをアクティブにしたり、テストを実行するためのテストスクリプトをアクティブにしたりと、さまざまなスクリプトをアクティブにすることができます。Dockerを使って統合テストを実行することもできます。Docker化されたアプリケーションの場合、テストコマンドを実行するためにDockerを実行すると、データベースであるかどうかに関わらず、テスト処理が実行されます。テスト用のスクリプトが書けるものなら何でもDockerで書くことができます。

###ステップ4：Dockerを使って環境への依存性を記述する
アプリケーションは画像だけではできませんが、他のアプリケーションでなければデータベースに依存しています。例えば、データテストを行う際にはデータベースが必要になります。

DockerにはDocker Composeというツールもあり、複数のDockerイメージを管理することができます。Docker Composeの使い方は以下の手順を参考にしてください。

1、アプリケーション環境を記述するDockerファイルを書く
Dockerファイルにプロジェクトディレクトリが何であるかを記述し、コードディレクトリに要件ファイルをコピーしてコードディレクトリの下にコピーし、rubyプログラムをpipでインストールして実行します。
2、.ymlを使って依存関係を記述する
ほとんどの状況では、単一のコンテナを使用してもほとんどの問題は解決しません。.ymlを使って、1つ以上のWebアプリケーションやデータベースなどを記述することができます。
アプリケーションがデータベースに依存する必要がある場合は、リンクを書いて「リンクDB」という名前を付けることができます。DockerのComposeコマンドを使うことで、Dockerイメージのグループを実行することができ、その中の依存関係をcompose .ymlを使って記述することができるようになります。

1、Dockerを使用して全体の統合または実行環境を記述する
Dockerの起動後、アプリにはロードバランサーやデータベース、ファイルストレージ、キャッシュなどの項目が必要になる場合があります。

- データベース
Dockerはデータベースの作成場所や作成手段を気にしません。開発管理の過程で、DBを起動する必要がある場合は、対応する公式ソースからDBコンテナを引っ張ってくる必要があります。例えば、MySQL DB5.7を使用する必要がある場合、対応する設定を見るためにMySQL DBのコンテナを起動したり、必要に応じていくつかの言語の記述を修正したりします。Docker Composeで実行することができます。1行目に依存関係を書いてMySQL5.7を実行する、2行目に環境変数を書いて設定ファイルを自分のものに置き換える、起動パスワードを設定してポートを3306にするなどして起動します。

Webアプリケーションをテストするには、MySQLのIDを書く必要はなく、「compose」で説明したMySQLのようにMySQLだけでも良いです。そして、パスワードを入力してデータベースへのアクセスを取得します。Redisの場合は、名前を付けてポートを提供するだけで、キャッシュサービスが必要なだけです。

- ロードバランサ


ロードバランシングも簡単で、nginxとHaproxyはどちらも公式ツールを提供しています。開発者にとってより大きな関心事は、Dockerを使ってアプリを記述することです。記述が終わったら、「compose」を済ませ、nginxのバージョンと設定を指定してアプリを実行します。

- ストレージ


vを使ってホストマシンにマウントし、データベースと初期化データをローカルディレクトリに保存します。これにより、実行のたびにアプリを初期化するのではなく、クリックしてから実行することができます。
本番環境の実行中は、実装に関わらずデータの保存はクラウドサーバーで行います。NASやAlibaba Cloud Object Storage Services（OSS）を利用していても、SDKやAPIを利用してデータをクラウドストレージデバイスにアップロードするのではなく、ローカルディレクトリの下にディレクトリをまとめることができます。

#Docker化されたデリバリープロセス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/d787e7e7-d051-9d31-961c-c9b3b9004b4f.png)

開発者はコード、設定、テストスクリプトに加えて、Dockerfileを書く必要があります。コードをコードリポジトリにプッシュすると、CIサービスはコードリポジトリフックを介して新しいコミットを伝えます。その後、ビルドとUTのためのコードをプルしてコピーします。ビルドプロセスの間、CIサービスは依存しているイメージをDockerレジストリからプルし、ビルドプロセスが完了すると、イメージをDockerレジストリのユニットにプッシュします。その後、CIはCDに通知するフックを持ち、Deploy ServiceはDocker、イメージの記述、Composeの記述に基づいて、イメージをプレテスト、テスト、本番環境にデプロイします。

デプロイの全体の流れは、レジストリからビルド可能なイメージを引っ張ってきて実行するというものです。最も複雑な内容はイメージと「Compose」ファイルの中にあるため、全体のプロセスが簡略化されています。

#結論
1. Docker デリバリーは何をもたらすのか？
開発がより明確になり、開発者にとってはより柔軟な開発が可能になります。以前はJavaの依存性が気になっていて、ローカルでJava環境を構築するのはかなり大変でした。しかし、その懸念が環境全体の依存性に移行したことで、Java環境の構築が格段に楽になりました。この方法であれば、O&M担当者はソフトウェアの依存関係でスケジュールを変更する必要がなくなり、常に構成を変更する必要がなくなります。Dockerは何に適用できますか？すべてのプロジェクトと環境をすべての人に提供します。 また、DevOpsの最も効果的な実装でもあります。Dockerを使えば、プログラミングを運用に適用し、開発プラクティスを利用して環境運用を管理することができます。

2. どのようなシナリオをDocker化すべきか？
これに関連する完全な定義はまだ出てきていません。しかし、私の理解では、コンテナ化の最大のメリットは、ライフサイクルの短縮とステートレス化の実現だと考えています。例えば、REST APIやCI/CDなどのWebアプリケーションであれば、テスト中にDockerコンテナを丸ごと引っ張って実行し、テスト終了後に破棄することでリソースの占有を回避することができます。タスクを実行するプロセスでは、Dockerを利用することでリソースを節約することができます。

データベース、特にストレージ用のデータベースはDocker化が最も難しいため、コンテナの恩恵を直接受けられない場合があります。サーバーがはるかに大きな負荷を負担する場合、それはファイルストレージとして機能します。しかし、これは実行できないわけではなく、あまり意味がないかもしれません。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*