Dockerを使う開発が増えてきました。これまで、私は開発環境でのDB構築にDockerを使っていて、PostgreSQLのコンテナを利用し、ローカル環境のデータベースとして使っていました
Dockerの説明で、よく「ミドルウェアやアプリケーションをまとめて、アプリケーションの実行環境を作れる」というものを見かけますし、「Dockerでデプロイしました!」という記事も見かけます。
最近になってSpring Bootアプリを内包したDockerイメージの作り方がわかりました。開発環境と本番環境の違いを気にせず、どこでも同じ環境を再現できるようになり、デプロイの手間が大幅に削減されました!
Spring BootってTomcat内包しているって全然知りませんでした・・・(依存関係に寄りますが)
今回は、アプリ(Spring Boot、またはVue.js)を内包したDockerイメージの作成からAWS ECRへのプッシュについてまとめていきます。
Dockerについて
Dockerはアプリケーションをコンテナと呼ばれる単位で動かす仮想化技術です。ローカルで作成した環境(ランタイムライブラリやアプリケーション)をそのまま本番環境に持ち込むことができ、環境の違いがかなり減ります。
仮想環境のため、ホストOSの環境の変化にも影響を受けにくく、ホストOSのメンテナンスも楽になります。例えば、OSやパッケージのバージョンアップをしても、Dockerコンテナ内のアプリには影響を与えないので安心して作業ができます。
さらに、Dockerの大きな魅力のひとつがその軽さです。従来の仮想マシンはOSごと仮想化するため、多くのリソースを消費しましたが、DockerはホストOSのカーネルを共有する仕組みを採用しているため、非常に効率的です。その結果、コンテナの起動が速く、リソース消費も少ないので、複数の環境を並行して使う場合でもパフォーマンスを維持できます。
AWS ECRについて
ECRは「Elastic Container Registry」の略で、AWSが提供するDockerイメージ管理サービスです。簡単に言うと、ECRを使えばDockerイメージを保存して、必要なときにすぐ引き出せる便利な仕組みです。
ECRに保存したDockerイメージはAWSの他のサービス(ECSやFargate、EC2など)と連携できるので、アプリのデプロイがスムーズに進みます。
使用するアプリ
- Docker
- AWS CLI V2
1. IAMアカウントの作成
ローカルのDockerからAWS ECRのリポジトリにプッシュするためには、適切な権限を持ったIAMユーザーが必要です。以下はIAMアカウントの作成手順です。
- AWS Management Consoleにログインし、IAMサービスを開きます。
- ユーザーを追加をクリックし名前を指定します。
- アクセスの種類で「プログラムによるアクセス」を選択します。
- 権限の設定で、既存のポリシーを直接アタッチするオプションを選択し、
AmazonEC2ContainerRegistryPowerUser
ポリシーを選択します。 - 作成されたアクセスキーとシークレットキーを保存します。
- ホームディレクトリにある、
.aws/credencials
にアクセスキーとシークレットキーを追記します。.aws/credencials
ファイルがない場合は作成してください。
以下が.aws/credentials
のサンプルです。ここでは、プロファイル名をECRUser
とします。
[ECRUser]
aws_access_key_id=<アクセスキー>
aws_secret_access_key=<シークレットキー>
これで、DockerからECRにアクセスする準備が整いました。
2. ECRでリポジトリの作成
ECRでDockerイメージを保存するには、最初にリポジトリを作成する必要があります。
AWS Management Consoleからリポジトリを作成する手順:
- ECRのコンソールを開く。
- “リポジトリを作成” をクリック。
- リポジトリ名を指定。
これで、リポジトリの作成が完了です。
3. Dockerイメージの作成
ECRリポジトリにプッシュするためのイメージを作成します。まずは、Dockerfile
を作成します。今回のDockerfile
はSpring BootアプリとVue.jsアプリが動作するDockerイメージをそれぞれ作成する想定です。
Spring Bootアプリが動作するDockerfile
# Amazon Corretto 21(軽量版)をベースに、Spring Bootアプリケーションを実行するためのDockerfile
# 開発に使用しているディストリビューションに合わせてください。
FROM amazoncorretto:21.0.5-alpine
# Spring Bootアプリケーションのjarファイルをコンテナ内にコピー
COPY <SpringBootをビルドしたjarファイル> /app/app.jar
# コンテナ内で使用するポート
# ここでは実際にポートを開放しているわけではなく、ドキュメントとしてのみの意味合い
EXPOSE 8080
# コンテナ起動時に実行するコマンド
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
Spring BootをビルドしたjarファイルにはTomcatが内包されているため、 java -jar <jarファイル>
でSpring Bootアプリが起動します。
Vue.jsアプリが動作するDockerfile
# alpine linuxベースのnginxイメージを使用
# nginxは約133MBあるが、nginx:alpineは約19MBと軽量
FROM nginx:alpine
# vue.jsアプリケーションのビルド結果をコンテナ内にコピー
COPY <Vue.jsビルドディレクトリ> /usr/share/nginx/html
# nginxの設定ファイルをコンテナ内にコピー
COPY push-docker-image/nginx.conf /etc/nginx/conf.d/default.conf
# コンテナ内で使用するポート
# ここでは実際にポートを開放しているわけではなく、ドキュメントとしてのみの意味合い
EXPOSE 80
# コンテナ起動時に実行するコマンド
CMD ["nginx", "-g", "daemon off;"]
以下のコマンドで、Dockerイメージを作成します。
docker build -t <name>:<tag> -f <Dockerfile名> .
4. DockerイメージをECRにプッシュ
ローカルにDockerイメージを作成したら、次にECRにプッシュします。
まず、ECRにログインします。--profile
オプションにはECRにプッシュできるプロファイルを指定します。先程のサンプルだとECRUser
を指定します。--profile
を省略するとdefault
が使われます。
aws ecr get-login-password --region <リージョン> --profile <プロファイル名> | docker login --username AWS --password-stdin <リポジトリURL>
ローカルのイメージのタグとリモートのタグの関連付けをします。
docker tag <name>:<tag> <リポジトリURL>:<tag>
ローカルのイメージをリモートにプッシュします。
docker push <リポジトリURL>:<tag>
これで、ECRへのイメージがプッシュが完了です。
5. ECRからイメージをダウンロード&コンテナ作成
ECRに保存されたDockerイメージをダウンロードし、コンテナを作成して実行します。
1. ECRへログイン
まず、ECRリポジトリにアクセスできるように、Dockerでログインします。
aws ecr get-login-password --region <リージョン> --profile <プロファイル名> | docker login --username AWS --password-stdin <リポジトリURL>
2. イメージをプル
ECRからDockerイメージを取得します。EC2からECRにプッシュされたDockerイメージをプルするには権限が必要です。マネージドポリシーを使う場合はAmazonEC2ContainerRegistryReadOnly
が良いと思います。
docker pull <リポジトリURL>:<タグ>
3. コンテナを作成・実行
取得したイメージを使ってコンテナを起動します。
# Spring Boot
docker run -d -p 8080:8080 <Spring BootアプリのリポジトリURL>:<タグ>
# Vue.js
docker run -d -p 80:80 <Vue.jsアプリのリポジトリURL>:<タグ>
-d
オプションを指定するとバックグラウンドで起動します。-p
でホストのポート番号とコンテナのポート番号を紐づけます。
Spring Bootアプリに環境変数(プロファイル指定)を渡す場合は以下のようにします。(環境変数を渡す方法はいくつかあります)
docker run -d -p 8080:8080 \
--env SPRING_PROFILES_ACTIVE=production \
<リポジトリURL>:<タグ>
4. 動作確認
コンテナの動作を確認するため、以下のコマンドでコンテナの一覧を表示します。
docker ps
また、コンテナのログを確認する場合は以下のコマンドを実行します。
これで、ECRから取得したイメージを利用してコンテナを作成し、実行することができます。
おわりに
AWS ECRを使うと、Dockerイメージの管理やデプロイがめちゃくちゃ楽になります。ECSやFargateと組み合わせれば、インフラの管理もほぼお任せできて快適です。(まぁ、まだECSを使ったデプロイをしたことはないのですが・・・)
今後はCI/CDパイプラインを組んで、ECRへのプッシュやECSへのデプロイを自動化して、もっと効率的にデプロイできるようにしたいです。