Unity ML-AgentsのDockerイメージを作成するのに、AWS CodeBuild(CodeBuild)を利用してみました。
CodeBuildでUnity ML-Agentsのソースを取得してビルド、ビルドができたらAmazon Elastic Container Registry(ECR)のリポジトリにイメージをPushします。
Unity ML-AgentsやCodeBuildについては省略。
同じようなことをGCPのGoogle Cloud Buildでもやっているので、GCPな方はそちらをご参考ください。
Google Cloud Buildを利用してUnity ML-AgentsのDockerイメージを作成する(v0.9.1対応) - Qiita
https://qiita.com/kai_kou/items/5eabbaa2b564527e0b4e
前提
- AWSアカウントがある
- ローカルで
aws
コマンドが利用できる - ローカルでDockerが実行できる
手順
AWS CloudFormation(CFn)で環境構築する
CFnを利用して、必要となるリソースを作成します。
- InputBucket: S3バケット。ソース置き場(使わない)
- OutputBucket: S3バケット。アーティファクト(使わない)
- ECRRepository: ECRリポジトリ。DockerイメージをPushします
- CodeBuildServiceRole: CodeBuildで利用するサービスロール
- CodeBuildProject: CodeBuildのプロジェクト
InputBucket
とOutputBucket
は利用しないのですが、CodeBuildのプロジェクトを作成・実行する際に必須となるので用意しています。
テンプレート作成するのに下記を参考にさせてもらいました。
AWS CodeBuildを使ってDockerイメージをビルドし、Amazon EC2 Container Registry(ECR)へpushする | DevelopersIO
https://dev.classmethod.jp/tool/docker/20170225-codebuild-docker/
CodeBuild で Docker イメージに Git のコミットIDをタグ付けてバージョン管理する | DevelopersIO
https://dev.classmethod.jp/cloud/aws/docker-image-tag-git-commit-id-by-codebuild/
DockerイメージをCodeBuildでビルドする場合、プロジェクト作成時にPrivilegedMode
を指定しないとだめだったのがポイントです。
CodeBuildでDocker in Dockerする(CloudFormation) - Qiita
https://qiita.com/sot528/items/ab0285b9907a29be840a
AWS::CodeBuild::Project Environment - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html
ECRリポジトリにRepositoryPolicyText
を指定していますが、これはPushしたイメージを別のCodeBuildでPullする場合に必要となります。
CodeBuild の Amazon ECR サンプル - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html
---
AWSTemplateFormatVersion: 2010-09-09
Description: Create Unity ML-Agents Docker Image
Parameters:
ProjectName:
Description: Project Name for CodeBuild
Default: ml-agents-build-test
Type: String
InputBucketName:
Description: Input Bucket Name
Default: codebuild-input
Type: String
OutputBucketName:
Description: Output Bucket Name
Default: codebuild-output
Type: String
ECRRepositoryName:
Description: ECR Repository Name
Default: ml-agents
Type: String
Resources:
InputBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${InputBucketName}
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
OutputBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${OutputBucketName}
AccessControl: Private
PublicAccessBlockConfiguration:
BlockPublicAcls: True
BlockPublicPolicy: True
IgnorePublicAcls: True
RestrictPublicBuckets: True
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Sub ${ECRRepositoryName}
RepositoryPolicyText:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- ecr:GetDownloadUrlForLayer
- ecr:BatchGetImage
- ecr:BatchCheckLayerAvailability
CodeBuildServiceRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: !Sub CodeBuildPolicy-${ProjectName}
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}:*
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Effect: Allow
Resource:
- !Sub arn:aws:s3:::codepipeline-${AWS::Region}-*
Action:
- s3:PutObject
- s3:GetObject
- s3:GetObjectVersion
- Effect: Allow
Resource:
- !Sub arn:aws:s3:::${InputBucketName}/*
Action:
- s3:GetObject
- s3:GetObjectVersion
- Effect: Allow
Resource:
- !Sub arn:aws:s3:::${OutputBucketName}/*
Action:
- s3:PutObject
- Effect: Allow
Resource:
- "*"
Action:
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:GetAuthorizationToken
- ecr:InitiateLayerUpload
- ecr:PutImage
- ecr:UploadLayerPart
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
Description: this is a test prj
ServiceRole: !Ref CodeBuildServiceRole
Artifacts:
Location: !Ref OutputBucketName
Type: S3
Name: artifacts
Path: !Sub ${ProjectName}
NamespaceType: BUILD_ID
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:2.0
PrivilegedMode: True
Source:
Location: !Join [ "/", [ !Ref InputBucketName, "dummy.zip" ] ]
Type: S3
TimeoutInMinutes: 10
Tags:
- Key: Name
Value: !Ref ProjectName
テンプレートが用意できたらAWS CLIでスタック作成します。サービスロールを作成するので--capabilities CAPABILITY_IAM
が必要になります。
--stack-name
や--region
はお好みで。--parameters
を指定するとバケット名やプロジェクト名も指定できます。
> cd テンプレートがあるディレクトリ
> aws cloudformation create-stack \
--stack-name kai-ml-agents-build \
--template-body file://template.yaml \
--capabilities CAPABILITY_IAM \
--region ap-northeast-1 \
--parameters '[
{
"ParameterKey": "ProjectName",
"ParameterValue": "ml-agents-build-test"
},
{
"ParameterKey": "InputBucketName",
"ParameterValue": "kai-ml-agents-build-input"
},
{
"ParameterKey": "OutputBucketName",
"ParameterValue": "kai-ml-agents-build-output"
},
{
"ParameterKey": "ECRRepositoryName",
"ParameterValue": "ml-agents"
}
]'
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/kai-ml-agents-build/0fa901a0-f56f-11e9-b734-06fcc76a2472"
}
スタック実行が完了したか確認します。"CREATE_COMPLETE"
になったらOK。
> aws cloudformation describe-stacks \
--region ap-northeast-1 \
--stack-name kai-ml-agents-build \
--query "Stacks[0].StackStatus"
"CREATE_COMPLETE"
CodeBuildのビルド実行準備
作成したCodeBuildのプロジェクトでビルド実行するための前準備をします。
S3バケットにダミーファイルをアップロードする
Unity ML-Agentsのソースはビルド実行時に取得するので、ビルドに必要となるソースがありません。
それでも、CodeBuildでビルド実行するにはCFnでプロジェクト作成時に指定したSource.Location
のファイルがないとビルド実行時にダウンロードエラーとなるのでダミーのファイルを用意します。ファイルはZipファイルじゃないとだめでした。
> touch dummy.txt
> zip dummy.zip dummy.txt
adding: dummy.txt (stored 0%)
> aws s3 cp dummy.zip s3://kai-ml-agents-build-input/
upload: ./dummy.zip to s3://kai-ml-agents-build-input/dummy.zip
buildspec.yamlを用意する
CodeBuildのプロジェクトでビルド実行する際の手順を記述したbuildspec.yaml
を用意します。
version: 0.2
phases:
install:
runtime-versions:
docker: 18
pre_build:
commands:
- echo Clone ML-Agents...
- git clone https://github.com/Unity-Technologies/ml-agents.git -b $IMAGE_TAG --depth 1
- echo Logging in to Amazon ECR...
- $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
- nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay&
- timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
- AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
build:
commands:
- docker build -t $ECR_REPOSITORY_NAME:$IMAGE_TAG ./ml-agents
- docker tag $ECR_REPOSITORY_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME:$IMAGE_TAG
post_build:
commands:
- echo Pushing the Docker image...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME:$IMAGE_TAG
ポイントは以下となります。
DockerイメージをビルドするのにDockerデーモンを初期化する
DockerイメージをCodeBuildでビルドするのに、プロジェクト作成時にPrivilegedMode
を指定しましたが、ビルド時にもDockerデーモンを初期化する必要がありました。
AWS::CodeBuild::Project Environment - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html
ビルドが Docker デーモンと連係動作できるように、Docker デーモンも起動する必要があります。これを行う 1 つの方法は、以下のビルドコマンドを実行してビルド仕様のインストールフェーズで Docker デーモンを初期化することです。(指定したビルド環境イメージの提供元が Docker 対応の AWS CodeBuild である場合は、これらのコマンドを実行しないでください。)
pre_build:
commands:
(略)
- nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay&
- timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
(略)
ビルド実行する
buildspec.yaml
が用意できたらCodeBuildのプロジェクトでビルド実行します。
だいたい10分くらいでビルド完了します。CFnでプロジェクト作成時にタイムアウト時間を10分にしましたが、念の為--timeout-in-minutes-override
オプションで20分に変更しています。
> aws codebuild start-build \
--region ap-northeast-1 \
--project-name ml-agents-build-test \
--buildspec-override file://buildspec.yaml \
--timeout-in-minutes-override 20 \
--environment-variables-override '[
{
"name": "ECR_REPOSITORY_NAME",
"value": "ml-agents",
"type": "PLAINTEXT"
},
{
"name": "IMAGE_TAG",
"value": "0.9.1",
"type": "PLAINTEXT"
}
]'
{
"build": {
"id": "ml-agents-build-test:17bfb5c6-8c8e-480c-a445-9e5dbb4b6004",
"arn": "arn:aws:codebuild:ap-northeast-1:xxxxxxxxxxxx:build/ml-agents-build-test:17bfb5c6-8c8e-480c-a445-9e5dbb4b6004",
"startTime": 1571821284.995,
"currentPhase": "QUEUED",
"buildStatus": "IN_PROGRESS",
(略)
aws codebuild batch-get-builds
コマンドでビルドが完了したか確認します。各フェーズのステータスがSUCCEEDED
で最後に"phaseType": "COMPLETED"
があったらビルド完了です。
> aws codebuild batch-get-builds \
--region ap-northeast-1 \
--ids ml-agents-build-test:17bfb5c6-8c8e-480c-a445-9e5dbb4b6004 \
--query "builds[0].phases"
[
{
"phaseStatus": "SUCCEEDED",
"endTime": 1571821285.18,
"phaseType": "SUBMITTED",
"durationInSeconds": 0,
"startTime": 1571821284.995
},
{
"phaseStatus": "SUCCEEDED",
"endTime": 1571821286.424,
"phaseType": "QUEUED",
"durationInSeconds": 1,
"startTime": 1571821285.18
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "PROVISIONING",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 21,
"startTime": 1571821286.424,
"endTime": 1571821307.801
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "DOWNLOAD_SOURCE",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 0,
"startTime": 1571821307.801,
"endTime": 1571821308.509
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "INSTALL",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 0,
"startTime": 1571821308.509,
"endTime": 1571821308.667
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "PRE_BUILD",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 17,
"startTime": 1571821308.667,
"endTime": 1571821326.049
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "BUILD",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 744,
"startTime": 1571821326.049,
"endTime": 1571822070.764
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "POST_BUILD",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 38,
"startTime": 1571822070.764,
"endTime": 1571822109.51
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "UPLOAD_ARTIFACTS",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 0,
"startTime": 1571822109.51,
"endTime": 1571822109.701
},
{
"contexts": [
{
"message": "",
"statusCode": ""
}
],
"phaseType": "FINALIZING",
"phaseStatus": "SUCCEEDED",
"durationInSeconds": 2,
"startTime": 1571822109.701,
"endTime": 1571822111.876
},
{
"phaseType": "COMPLETED",
"startTime": 1571822111.876
}
]
AWS ECRのリポジトリからイメージを取得する
AWS ECRのリポジトリにイメージが登録されたか確認して、実際にイメージを取得・利用してみます。
<AWS_ACCOUNT_ID>
と<REGION>
は置き換えてください。
> aws ecr list-images \
--repository-name ml-agents \
--region <REGION>
{
"imageIds": [
{
"imageTag": "0.9.1",
"imageDigest": "sha256:b9da2732606536ada8d3eabe258ac44286ae8c0706c9325d008880a2f2855f1c"
}
]
}
# デフォルトレジストリに対してDockerを認証する
> $(aws ecr get-login --no-include-email --region <REGION>)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
> docker pull <AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/ml-agents:0.9.1
(略)
1b38598abf23: Pull complete
Digest: sha256:b9da2732606536ada8d3eabe258ac44286ae8c0706c9325d008880a2f2855f1c
Status: Downloaded newer image for <AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/ml-agents:0.9.1
<AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/ml-agents:0.9.1
> docker run -it --rm \
<AWS_ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com/ml-agents:0.9.1
▄▄▄▓▓▓▓
╓▓▓▓▓▓▓█▓▓▓▓▓
,▄▄▄m▀▀▀' ,▓▓▓▀▓▓▄ ▓▓▓ ▓▓▌
▄▓▓▓▀' ▄▓▓▀ ▓▓▓ ▄▄ ▄▄ ,▄▄ ▄▄▄▄ ,▄▄ ▄▓▓▌▄ ▄▄▄ ,▄▄
▄▓▓▓▀ ▄▓▓▀ ▐▓▓▌ ▓▓▌ ▐▓▓ ▐▓▓▓▀▀▀▓▓▌ ▓▓▓ ▀▓▓▌▀ ^▓▓▌ ╒▓▓▌
▄▓▓▓▓▓▄▄▄▄▄▄▄▄▓▓▓ ▓▀ ▓▓▌ ▐▓▓ ▐▓▓ ▓▓▓ ▓▓▓ ▓▓▌ ▐▓▓▄ ▓▓▌
▀▓▓▓▓▀▀▀▀▀▀▀▀▀▀▓▓▄ ▓▓ ▓▓▌ ▐▓▓ ▐▓▓ ▓▓▓ ▓▓▓ ▓▓▌ ▐▓▓▐▓▓
^█▓▓▓ ▀▓▓▄ ▐▓▓▌ ▓▓▓▓▄▓▓▓▓ ▐▓▓ ▓▓▓ ▓▓▓ ▓▓▓▄ ▓▓▓▓`
'▀▓▓▓▄ ^▓▓▓ ▓▓▓ └▀▀▀▀ ▀▀ ^▀▀ `▀▀ `▀▀ '▀▀ ▐▓▓▌
▀▀▀▀▓▄▄▄ ▓▓▓▓▓▓, ▓▓▓▓▀
`▀█▓▓▓▓▓▓▓▓▓▌
¬`▀▀▀█▓
Usage:
mlagents-learn <trainer-config-path> [options]
mlagents-learn --help
Dockerコンテナでmlagents-learn
コマンドが実行されたのが確認できました。やったぜ
実際にML-Agentsを動作させる手順は下記をご参考ください。
DockerでUnity ML-Agentsを動作させる(v0.9.1対応) - Qiita
https://qiita.com/kai_kou/items/0c2f3c7d22363fd91e4e
参考
DockerイメージをCodeBuildでビルドするのに、プロジェクト作成時にPrivilegedMode
を指定しましたが、ビルド時にもDockerデーモンを初期化する必要がありました。
Google Cloud Buildを利用してUnity ML-AgentsのDockerイメージを作成する(v0.9.1対応) - Qiita
https://qiita.com/kai_kou/items/5eabbaa2b564527e0b4e
AWS CodeBuildを使ってDockerイメージをビルドし、Amazon EC2 Container Registry(ECR)へpushする | DevelopersIO
https://dev.classmethod.jp/tool/docker/20170225-codebuild-docker/
CodeBuild で Docker イメージに Git のコミットIDをタグ付けてバージョン管理する | DevelopersIO
https://dev.classmethod.jp/cloud/aws/docker-image-tag-git-commit-id-by-codebuild/
CodeBuildでDocker in Dockerする(CloudFormation) - Qiita
https://qiita.com/sot528/items/ab0285b9907a29be840a
AWS::CodeBuild::Project Environment - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html
AWS::CodeBuild::Project Environment - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environment.html
Amazon ECR で AWS CLI を使用する - Amazon ECR
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/ECR_AWSCLI.html
CodeBuild のビルドの詳細を表示する - AWS CodeBuild https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/view-build-details.html#view-build-details-cli
ビルド環境の環境変数 - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-env-vars.html
CodeBuildでビルドプロジェクトを作成する-AWS CodeBuild
https://docs.aws.amazon.com/codebuild/latest/userguide/create-project.html#create-project-cli
CodeBuild のビルドの詳細を表示する - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/view-build-details.html
CodeBuild のビルド仕様に関するリファレンス - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html#runtime-versions-buildspec-file
CodeBuild でビルドを実行する - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/run-build.html#run-build-cli
CodeBuild の Docker サンプル - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-docker.html
Amazon ECR レジストリ - Amazon ECR
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/Registries.html#registry_auth
CodeBuild の Amazon ECR サンプル - AWS CodeBuild
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html