0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ドッカーイメージからECRへのデプロイ

0
Posted at

元ファイル(ドッカーファイル入り)

ドッカーイメージ

────────────────────────
手順1
準備するファイルを同じディレクトリに置く
────────────────────────
必要な最低ファイル
Dockerfile
pom.xml
src フォルダ
inport.sql
docker/startup.sh

構成例
project-root
├ Dockerfile
├ pom.xml
├ src
│ └ javaコード
├ inport.sql
└ docker
└ startup.sh

この状態でプロジェクトが正しくビルドできる前提で進める。

────────────────────────
手順2
Dockerfile の内容を確認し、目的を理解する
────────────────────────
この Dockerfile は二段階構成になっている。

1段階目
Maven を使って Java アプリをビルドし war ファイルを生成する

2段階目
Tomcat と MySQL を同一コンテナ内で動作させ、ビルド済みの war を ROOT.war として配置する

ENTRYPOINT で startup.sh が実行されることで、MySQLとTomcatの両方を起動する。

────────────────────────
手順3
docker build を実行してイメージを作成する
────────────────────────
プロジェクトのルートディレクトリで実行


docker build -t office-system:latest .

意味
-t でイメージ名とタグを設定
最後のドットはカレントディレクトリをビルドコンテキストとして指定

正しく終了すればイメージがローカルに作成される。

────────────────────────
手順4
イメージができたことを確認する
────────────────────────
docker images

一覧に office-system が表示されていれば成功。

────────────────────────
手順5
イメージからコンテナを起動する
────────────────────────
基本例

docker run -d --name office-system -p 8080:8080 -p 3306:3306 office-system:latest

ポイント
ポート 8080 は Tomcat の外部公開
ポート 3306 は MySQL の外部公開

起動後
http://localhost:8080
にアクセスするとアプリが表示される。

────────────────────────
手順6
ログを確認したい場合
────────────────────────
docker logs -f office-system

異常終了している場合のデバッグに必要。

────────────────────────
手順7
コンテナを停止・削除する場合
────────────────────────
停止
docker stop office-system

削除
docker rm office-system

────────────────────────
まとめ
────────────────────────
1 Dockerfile とアプリ関連ファイルを同じ場所に置く
2 docker build -t イメージ名 . でビルド
3 docker run でポートを公開して起動
4 ブラウザでアクセスして動作確認

# syntax=docker/dockerfile:1.6
# syntax=docker/dockerfile:1.6

# アプリケーションのビルド用ステージ(Maven)
FROM maven:3.9.6-eclipse-temurin-8 AS builder

# 作業ディレクトリを/appに設定
WORKDIR /app

# 依存関係情報(pom.xml)をコピー
COPY pom.xml .

# ソースコードをコピー
COPY src ./src

# テストをスキップしてMavenでビルド
RUN mvn -B -DskipTests clean package

FROM tomcat:8.5-jdk8-temurin-jammy
ENV MYSQL_DATABASE=csharp \
    MYSQL_ROOT_PASSWORD=csharp \
    TZ=Asia/Tokyo
USER root
RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mysql-server tini \
    && rm -rf /var/lib/apt/lists/*

COPY inport.sql /docker-entrypoint-initdb.d/inport.sql

RUN mkdir -p /run/mysqld \
    && chown mysql:mysql /run/mysqld \
    && chown -R mysql:mysql /var/lib/mysql \
    && rm -rf /var/lib/mysql/* \
    && if command -v mysql_install_db >/dev/null 2>&1; then \
        mysql_install_db --user=mysql --ldata=/var/lib/mysql; \
    else \
        mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql; \
    fi

RUN mysqld --user=mysql --datadir=/var/lib/mysql --skip-networking --socket=/run/mysqld/mysqld.sock --daemonize \
    && for i in $(seq 1 40); do \
        mysqladmin --protocol=socket ping && break; \
        sleep 1; \
    done \
    && mysql --protocol=socket -uroot -e "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" \
    && mysql --protocol=socket -uroot $MYSQL_DATABASE < /docker-entrypoint-initdb.d/inport.sql \
    && mysql --protocol=socket -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD'; FLUSH PRIVILEGES;" \
    && mysqladmin --protocol=socket -uroot -p$MYSQL_ROOT_PASSWORD shutdown

COPY --from=builder /app/target/OfficeSystem_Hibernate2.war /usr/local/tomcat/webapps/ROOT.war
COPY docker/startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh

EXPOSE 8080 3306
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/startup.sh"]
# syntax=docker/dockerfile:1.6
# syntax=docker/dockerfile:1.6

# アプリケーションのビルド用ステージ(Maven)
FROM maven:3.9.6-eclipse-temurin-8 AS builder

# 作業ディレクトリを/appに設定
WORKDIR /app

# 依存関係情報(pom.xml)をコピー
COPY pom.xml .

# ソースコードをコピー
COPY src ./src

# テストをスキップしてMavenでビルド
RUN mvn -B -DskipTests clean package

FROM tomcat:8.5-jdk8-temurin-jammy
ENV MYSQL_DATABASE=csharp \
    MYSQL_ROOT_PASSWORD=csharp \
    TZ=Asia/Tokyo
USER root
RUN apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mysql-server tini \
    && rm -rf /var/lib/apt/lists/*

COPY inport.sql /docker-entrypoint-initdb.d/inport.sql

RUN mkdir -p /run/mysqld \
    && chown mysql:mysql /run/mysqld \
    && chown -R mysql:mysql /var/lib/mysql \
    && rm -rf /var/lib/mysql/* \
    && if command -v mysql_install_db >/dev/null 2>&1; then \
        mysql_install_db --user=mysql --ldata=/var/lib/mysql; \
    else \
        mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql; \
    fi

RUN mysqld --user=mysql --datadir=/var/lib/mysql --skip-networking --socket=/run/mysqld/mysqld.sock --daemonize \
    && for i in $(seq 1 40); do \
        mysqladmin --protocol=socket ping && break; \
        sleep 1; \
    done \
    && mysql --protocol=socket -uroot -e "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" \
    && mysql --protocol=socket -uroot $MYSQL_DATABASE < /docker-entrypoint-initdb.d/inport.sql \
    && mysql --protocol=socket -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD'; FLUSH PRIVILEGES;" \
    && mysqladmin --protocol=socket -uroot -p$MYSQL_ROOT_PASSWORD shutdown

COPY --from=builder /app/target/OfficeSystem_Hibernate2.war /usr/local/tomcat/webapps/ROOT.war
COPY docker/startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh

EXPOSE 8080 3306
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/startup.sh"]

ECS(エキスプレスでの作成)

・ポートは8080を設定する、外部の443で来た場合にはローカルコンテナの8080を指し示すようにする為
・メモリは1G以上にしないと、途中で止まる
・ECRでも行けるがdockerhubの場合 jtths474/office-system:latest

AmazonLSでも同様

この JSON は ECS タスク定義(Task Definition) の内容。
意味とポイントを論理的に整理する。

────────────────────────
1
この JSON で定義されていること
────────────────────────
・タスクの名前(family)
・実行するコンテナの設定
・CPU/メモリの割り当て
・Fargate で動かす指定
・ログの送信先(CloudWatch Logs)
・ネットワークモード(awsvpc)

つまり 「ECS Fargate で 1つのコンテナ (office-system) を起動する設定」 を表している。

────────────────────────
2
コンテナ設定で重要な部分
────────────────────────

"image": "jtths474/office-system:latest"

Docker Hub にある自分のイメージを使う。

"portMappings": [
  {
    "containerPort": 8080,
    "hostPort": 8080
  }
]

タスク内のコンテナは 8080 番でアプリを公開する想定。

"logConfiguration"

CloudWatch Logs にログを送る設定。

────────────────────────
3
Fargate 起動に必要な設定
────────────────────────

"requiresCompatibilities": ["FARGATE"]
"networkMode": "awsvpc"
"cpu": "512"
"memory": "1024"
"executionRoleArn": "...ecsTaskExecutionRole"

Fargate の要件は満たしている。

────────────────────────
4
このタスク定義で起動するときに注意点
────────────────────────
コンテナ側では 8080 が公開される。
しかし Fargate は タスクを起動するだけでは外部アクセスできない

外部公開するために必要なもの
・サービス(ECS Service)
・ALB(Application Load Balancer)またはパブリック IP を付けた ENI
・セキュリティグループで 80/8080 のインバウンド許可
・サブネット(パブリック or プライベート+NAT)

この JSON には、それらは含まれていない。
これは タスク定義だけ

────────────────────────
5
起動手順の全体像
────────────────────────
① このタスク定義を登録
② ECS クラスターでサービスを作成
③ Fargate を選択
④ タスク数=1 など指定
⑤ VPC とサブネットを選択
⑥ セキュリティグループで 8080 を許可
⑦ 必要に応じて ALB を設定(推奨)

→ 最後にタスクが起動し、ロードバランサまたはパブリック IP 経由でアクセス可能になる。

────────────────────────
6
改善点(必須ではないが推奨)
────────────────────────
現在は環境変数が空

"environment": []

アプリが MySQL 内部組み込み型の場合は問題ないが
外部 RDS や Secrets Manager を利用するなら
ここに DB 接続文字列を指定する。

"environment": [
  { "name": "DB_HOST", "value": "xxxxxxx.ap-northeast-1.rds.amazonaws.com" },
  { "name": "DB_USER", "value": "admin" }
]

────────────────────────
7
結論
────────────────────────
この JSON は正しいタスク定義。
しかし タスク定義だけではアクセスできない
サービス作成とネットワーク設定が必須。

────────────────────────
必要なら次のどれを解説できる
────────────────────────
A サービス作成手順(クリック手順で案内)
B ALB + Fargate 構成図
C パブリック IP アクセス構成(最小構成)
D GitHub Actions で ECR → ECS 自動デプロイの設定例

{
    "compatibilities": [
        "EC2",
        "FARGATE",
        "MANAGED_INSTANCES"
    ],
    "containerDefinitions": [
        {
            "cpu": 512,
            "environment": [],
            "essential": true,
            "image": "jtths474/office-system:latest",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/aws/ecs/default/office-system-dba2-d00e",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "memoryReservation": 1024,
            "mountPoints": [],
            "name": "Main",
            "portMappings": [
                {
                    "containerPort": 8080,
                    "hostPort": 8080,
                    "protocol": "tcp"
                }
            ],
            "secrets": [],
            "volumesFrom": []
        }
    ],
    "cpu": "512",
    "enableFaultInjection": false,
    "executionRoleArn": "arn:aws:iam::208620526672:role/service-role/ecsTaskExecutionRole",
    "family": "default-office-system-dba2",
    "memory": "1024",
    "networkMode": "awsvpc",
    "placementConstraints": [],
    "registeredAt": "2025-12-02T03:13:11.008Z",
    "requiresAttributes": [
        {
            "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
        },
        {
            "name": "ecs.capability.execution-role-awslogs"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.21"
        },
        {
            "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
        },
        {
            "name": "ecs.capability.task-eni"
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "revision": 1,
    "runtimePlatform": {
        "cpuArchitecture": "X86_64",
        "operatingSystemFamily": "LINUX"
    },
    "status": "ACTIVE",
    "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:208620526672:task-definition/default-office-system-dba2:1",
    "volumes": [],
    "tags": []
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?