🍣

ECSでPHPのDocker Imageを動かすときの注意点

2021/07/29に公開

発生したこと

ローカルで動かしていたPHP + Nginx + Mysqlの3層webアーキテクチャのDockerコンテナをECS + Faragte構成で動かそうとデプロイしたところ動かない。。
Nginxは問題なさそう。じゃあPHPかと思ってlogと睨めっこしていたところ、どうやらdocker-php-entrypointがローカル環境では動いていたっぽいが、デプロイ後は動いていないということがわかりました。

ENTRYPOINT ["docker-php-entrypoint"]

原因

migrationを実行しようとECSのタスク定義でENTRYPOINTの設定をしたのですが、Dockerの仕組み上ENTRYPOINTやCMDは最後に実行したものしか動かない。つまりmigrationの処理で上書きをしてしまって、本来動いていたdocker-php-entrypointが動かなくなったのが原因でした。
ローカルではコンテナの起動時にmigrationを実行するとかしないから、わからなかった。。

解決方法

本来のdocker-php-entrypointとmigrationの実行を両方すれば良いので、解決方法としては2パターンあります。

shellスクリプトなどを作り、その中で実行する

こちらの記事に詳しく書いてます。

https://sleepless-se.net/2018/05/26/dockerで複数cmdを実行する方法/#:~:text=DockerでCMDを複数実行する方法,-前置きが長く&text=CDMを複数行実行,実行できるというわけです。

migrationを実行するコンテナを用意する

今回はこの方法で実装しました。
同じPHPのイメージを使うのですが、migration用のコンテナはmigrationを実行後停止しても良いのでdocker-php-entrypointの処理は動かなくて問題無し。
PHPのコンテナは動かしたいので、docker-php-entrypointを実行させておく。
ECSのタスク定義はこんな感じ。ECSのタスク定義の細かい説明は割愛します。

[
    {
        "dnsSearchDomains": null,
        "environmentFiles": null,
        "logConfiguration": {
          "logDriver": "awslogs",
          "secretOptions": null,
          "options": {
            "awslogs-group": "/ecs/NGINX-prod",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "ecs",
            "awslogs-datetime-format": "%Y-%m-%d %H:%M:%S"
          }
        },
        "entryPoint": null,
        "portMappings": [
          {
            "hostPort": 80,
            "protocol": "tcp",
            "containerPort": 80
          }
        ],
        "command": [],
        "linuxParameters": null,
        "cpu": 0,
        "environment": [],
        "resourceRequirements": null,
        "ulimits": null,
        "dnsServers": null,
        "workingDirectory": null,
        "secrets": null,
        "dockerSecurityOptions": null,
        "memory": null,
        "memoryReservation": null,
        "volumesFrom": [],
        "stopTimeout": null,
        "image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/nginx",
        "startTimeout": null,
        "firelensConfiguration": null,
        "dependsOn": null,
        "disableNetworking": null,
        "interactive": null,
        "healthCheck": null,
        "essential": true,
        "links": null,
        "hostname": null,
        "extraHosts": null,
        "pseudoTerminal": null,
        "user": null,
        "readonlyRootFilesystem": null,
        "dockerLabels": null,
        "systemControls": null,
        "privileged": null,
        "name": "NGINX"
      },
      {
        "dnsSearchDomains": null,
        "environmentFiles": null,
        "logConfiguration": {
          "logDriver": "awslogs",
          "secretOptions": null,
          "options": {
            "awslogs-group": "/ecs/APP-prod",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "ecs",
            "awslogs-datetime-format": "%Y-%m-%d %H:%M:%S"
          }
        },
        "entryPoint": null,
        "workingDirectory": null,
        "portMappings": [
          {
            "hostPort": 9000,
            "protocol": "tcp",
            "containerPort": 9000
          }
        ],
        "command": [],
        "linuxParameters": null,
        "cpu": 0,
        "environment": [
          // DB_PORTとか設定する
        ],
        "resourceRequirements": null,
        "ulimits": null,
        "dnsServers": null,
        "secrets": null,
        "dockerSecurityOptions": null,
        "memory": null,
        "memoryReservation": null,
        "volumesFrom": [],
        "stopTimeout": null,
        "image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/app",
        "startTimeout": null,
        "firelensConfiguration": null,
        "dependsOn": null,
        "disableNetworking": null,
        "interactive": null,
        "healthCheck": null,
        "essential": true,
        "links": null,
        "hostname": null,
        "extraHosts": null,
        "pseudoTerminal": null,
        "user": null,
        "readonlyRootFilesystem": null,
        "dockerLabels": null,
        "systemControls": null,
        "privileged": null,
        "name": "APP"
      },
      {
        "dnsSearchDomains": null,
        "environmentFiles": null,
        "logConfiguration": {
          "logDriver": "awslogs",
          "secretOptions": null,
          "options": {
            "awslogs-group": "/ecs/APP-prod",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "ecs",
            "awslogs-datetime-format": "%Y-%m-%d %H:%M:%S"
          }
        },
        "entryPoint": null,
        "workingDirectory": "/work/backend",
        "portMappings": [
          {
            "hostPort": 9001,
            "protocol": "tcp",
            "containerPort": 9001
          }
        ],
        "command": [
          "php",
          "artisan",
          "migrate:fresh",
          "--force",
          "--seed"
        ],
        "linuxParameters": null,
        "cpu": 0,
        "environment": [
          // DB_PORTとか設定する
        ],
        "resourceRequirements": null,
        "ulimits": null,
        "dnsServers": null,
        "secrets": null,
        "dockerSecurityOptions": null,
        "memory": null,
        "memoryReservation": null,
        "volumesFrom": [],
        "stopTimeout": null,
        "image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/app",
        "startTimeout": null,
        "firelensConfiguration": null,
        "dependsOn": null,
        "disableNetworking": null,
        "interactive": null,
        "healthCheck": null,
        "essential": false,
        "links": null,
        "hostname": null,
        "extraHosts": null,
        "pseudoTerminal": null,
        "user": null,
        "readonlyRootFilesystem": null,
        "dockerLabels": null,
        "systemControls": null,
        "privileged": null,
        "name": "MIGRATE"
      }
]

重要なのはここですね。migrationのコンテナは停止しても、タスク自体は動かし続けたいのでessentialはfalseにしておきます。

"essential": false,

いやー、ECS + Fargateの構成は難しい。。
いろんなところで躓くので、早く知見をもっとためたいな。

Discussion