1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

メモ:CodePipelineでDockerImageを作る

Last updated at Posted at 2021-12-22

CI/CDツールはAWSのCodePipelineを軽く使った事があるので、一応備忘録として書いておく。
(jenkisは使った事がないが、別途見ておきたい)

CodePipeline

基本的には

  • コード管理であるgit (CodeCommitやGitHub)
  • ビルド、テストを行う(CodeBuildもしくはJenkis。ECRにPushする)
  • デプロイはCodeDeployでECSでリリースなど

のセットをpipelineで作成する。
起動トリガーはgitへのPushやS3へのファイルアップロード等が選択可能
途中で停止させて、ボタンを押さないと進まないようにすることも可能

設定方法

terraformで作成する場合を想定する。Formationでも大差はない、はず?
少し前のバージョンで書いたコードなので今のterraformで使う場合は修正が必要か。

まずはaws_codebuild_projectでビルドプロジェクトを作成する。
var.やlocal.は変数設定している箇所。
ECRやCodeCommitのリポジトリは既に存在しているという前提。
(大量に作るのでない限り、リポジトリはわざわざIaCで管理する必要なさそうな気がする)
AWS公式も参照

resource "aws_codebuild_project" "codebuild_project" {
  name = local.CodeBuildName
  service_role = "arn:aws:iam::${local.account}:role/CodeBuildServiceRole"

  artifacts {
    type = "NO_ARTIFACTS"
  }

  # ビルド環境の設定
  environment {
    compute_type                = "BUILD_GENERAL1_SMALL"
    image                       = "aws/codebuild/standard:2.0"
    type                        = "LINUX_CONTAINER"
    image_pull_credentials_type = "CODEBUILD"

    # ここで設定した値をbuildspeck.ymlで使える
    environment_variable {
      name  = "AWS_DEFAULT_REGION"
      value = "ap-northeast-1"
    }

    environment_variable {
      name  = "AWS_ACCOUNT_ID"
      value = local.account
    }

    # ECRは事前に作成
    environment_variable {
      name  = "ECR_REPOSITORY_NAME"
      value = local.ECRName
    }

    environment_variable {
      name  = "SYSTEM_ID"
      value = var.SystemID
    }

    environment_variable {
      name  = "CONTAINER_NAME"
      value = local.ContainerName
    }

    privileged_mode = "true"
  }

  # クラウドウォッチにログ出力する場合
  logs_config {
    cloudwatch_logs {
      group_name = local.CloudWatchLogName
      status = "ENABLED"
      stream_name = var.SystemID
    }
  }

  // gitHubの場合は別途参照
  source {
    type            = "CODECOMMIT"
    location        = "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/${var.GitReposName}"
  }
}

ビルドするマシンは公式から選択
イメージも公式を見ると良い。
ここを見るとaws/codebuild/standard:2.0は時代遅れっぽい。

CodeCommitをソースにしているが、GitHubの場合はパラメータストアにトークン保存した上で以下のようにする。
CodeCommitも悪くはないのだが、本番とテストでアカウントが分かる事を考えるとgitHubが使えるならそちらで良い気はする。
(専用線経由でアクセスできるからCodeCommitを使いたい、というような要望はあるかもしれないけど)

source {
    type                = "GITHUB"
    location            = var.github_repository_location
    git_clone_depth     = 1
    report_build_status = true # 結果をリポジトリに通知する場合はtrueを指定
  }

そして、このビルド設定をCodePipelineに適用する。

resource "aws_codepipeline" "codepipeline" {
  name = local.CodePipelineName

  # ロールは事前に作成されているとする
  role_arn = "arn:aws:iam::${local.account}:role/CodePipelineServiceRole"

  # S3の名前は自分の所有しているものにする
  artifact_store {
    location = "s3_codepipeline"
    type     = "S3"
  }

  # Source,Build,Deployの順番で実行されるので、設定していく。
  stage {
    name = "Source"
    action {
      name             = "Source"
      category         = "Source"
      owner            = "AWS"
      provider         = "CodeCommit"
      version          = "1"
      output_artifacts = ["source_output"]

      configuration = {
        RepositoryName   = var.GitReposName
        BranchName = "master"
        PollForSourceChanges = "false" # CloudWatchで検出するのでfalseにする
      }
    }
  }

  stage {
    name = "Build"
    action {
      name             = "Build"
      category         = "Build"
      owner            = "AWS"
      provider         = "CodeBuild"
      input_artifacts  = ["source_output"]
      output_artifacts = ["build_output"]
      version          = "1"

      configuration = {
        ProjectName =   local.CodeBuildName

      }
    }
  }

  # ECSにデプロイ
  stage {
    name = "Deploy"
    action {
      name             = "Deploy"
      category         = "Deploy"
      owner            = "AWS"
      provider         = "ECS"
      input_artifacts  = ["build_output"]
      version          = "1"

      configuration = {
        ClusterName = local.ECSClusterName
        ServiceName = local.ECSServiceName
        FileName    = "imagedefinitions.json"

      }
    }
  }
}

ソースコードの検知はCloudWatchを使う

resource "aws_cloudwatch_event_rule" "event_rule" {
  name        = local.CloudWatchEventName
  description = "Amazon CloudWatch Events rule to automatically start your pipeline when a change occurs in the AWSCodeCommit."

  event_pattern = <<-JSON
  {
    "source": [
      "aws.codecommit"
    ],
    "detail-type": [
      "CodeCommit Repository State Change"
    ],
    "resources": [
      "arn:aws:codecommit:ap-northeast-1:${var.git_account}:${var.GitReposName}"
    ],
    "detail": {
      "event": [
        "referenceCreated",
        "referenceUpdated"
      ],
      "referenceType": [
        "branch"
      ],
      "referenceName": [
        "master"
      ]
    }
  }
  JSON

  depends_on = ["aws_codepipeline.codepipeline"]
}

resource "aws_cloudwatch_event_target" "event_target" {
  rule      = aws_cloudwatch_event_rule.event_rule.name
  target_id = aws_cloudwatch_event_rule.event_rule.name
  arn       = aws_codepipeline.codepipeline.arn
  role_arn  = "arn:aws:iam::${local.account}:role/StartPipelineExecutionRole"
}

これでgit上のファイルが変わった場合に動くように出来る。
特定のファイルが変わった場合のみビルド場合は.shでコントロールするといった方法があった。
機能追加されてフィルタをかけられるようになっている、というような情報は知らない。

S3へのファイルをアップロードをトリガーとする場合は以下のようにソースを設定する。
こちらはkeyでファイル名を指定できるので、例えばxyz.warがアップロードされるとpipelineが走る、というように出来る。

resource "aws_cloudwatch_event_rule" "event_rule" {
  name        = local.CloudWatchEventName
  description = "Amazon CloudWatch Events rule to automatically start your pipeline when a change occurs in the AWSCodeCommit."

  event_pattern = <<-JSON
  {
    "source": [ "aws.s3" ],
    "detail-type": [ "AWS API Call via CloudTrail" ],
    "detail": { 
      "eventSource": [ "s3.amazonaws.com" ],
      "eventName": [ "PutObject", "CompleteMultipartUpload", "CopyObject" ],
      "requestParameters": {
        "bucketName": [ "s3-codepipeline" ],
        "key": [ "${local.CodePipelineName}/${var.warfile}" ]
      }
    }
  }
  JSON

  depends_on = ["aws_codepipeline.codepipeline"]
}

これらのAWS上の設定をした上で、実際にビルドするには設定ファイルbuildspec.ymlがgit上に必要となる。

version: 0.2

env:
  # Dockerhubへのアクセストークンをパラメーターストアから読み込んでおく
  parameter-store:
    DOCKER_USER: docker-hub-user
    DOCKER_TOKEN: docker-hub-token

phases:
  # 自動テストを行う場合はinstallセクションのcommandsでテストツールインストール
  install:
    runtime-versions:
      docker: 18
  # ログイン等、ビルド前の準備
  # AWS_ACCOUNT_ID等はterraform側で設定した値
  pre_build:
    commands:
      - echo Logging in to Amazon ECR ...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
      - REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - echo $DOCKER_TOKEN | docker login -u $DOCKER_USER --password-stdin
  build:
    # ここではS3から.warをコピーしてdockerImageを作成する想定
    commands:
      - aws s3 cp s3://s3-codepipeline/$PIPELINE_NAME/$SYSTEM_WAR ./$SYSTEM_WAR
      - echo Build started on `date`
      - echo Building the Docker image...          
      - docker build -t $REPOSITORY_URI:latest .
      - echo docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    # イメージをECRにプッシュする
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME:$IMAGE_TAG > imagedefinitions.json
artifacts:
  files: imagedefinitions.json

これでビルドが動くがDockerイメージを作成しているので、Dockerfileが必要なので
例えばtomcat9+jdk8のイメージにwarファイルを追加するようなものを用意して配置しておく。

#
# VERSION 0.0.1
#


FROM tomcat:9.0.41-jdk8-corretto
LABEL maintainer="test@test.com"
ARG MEM_MX="2048m"
ARG MEM_MS="64m"
ARG APP_WARFILE="./xyz.war"


RUN echo $CATALINA_HOME
RUN echo $CATALINA_HOME/webapps/

ADD ./app/conf/server.xml $CATALINA_HOME/conf/server.xml

ENV CATALINA_OPTS "-server -Xmx$MEM_MX -Xms$MEM_MS 


# check Web application
ADD $APP_WARFILE $CATALINA_HOME/webapps

WORKDIR $CATALINA_HOME/bin

これで一連の動きは出来る。
テストレポート等を作る場合はこことか公式を参考に。
buildでテストを実行するコマンドを書いた上でreportsセクションを追加してやればよい。

途中で承認処理を付ける場合
公式

おわり

1
1
1

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?