Help us understand the problem. What is going on with this article?

GitlabのCIでnpm+docker+git+awscliの実行環境構築

More than 1 year has passed since last update.

追記

ecs_deploy.shの実行権限がなかったので、chmod 500 ./ci/ecs_deploy.shを追記しました

背景

趣味のwebアプリ開発環境を一通り整えたが、最後のCIの部分を全く実装していかなった
GitHubを使っていたらCodePipelineを使って楽々ECSにデプロイできたのだが、今回はGitlabで作成してしまった
そしてGitHubに移す気力はない

対象読者

  • ECS/ECRでの継続デプロイを理解している人

目的

理想は、masterにプッシュしたら、自動でgitlab runnerが走って自動でecrを更新しecsのサービスも更新してほしい(贅沢)

今回の僕のweb環境は以下のようになっています。
RESTfulなので、フロントエンドとAPIサイドに分かれています。

├── Dockerfile
├── README.md
├── docker-compose.yml
├── front     <=フロントエンド側の開発ディレクトリ
├── nginx.conf
└── phalcon     <= webアプリケーションのディレクトリ
    ├── (略)
    ├── public   <= nginxのrootディレクトリ

これを踏まえて、CIサーバーでやらせたいことを掘り下げると、、、

  • dockerコマンドで、ビルドしたイメージをECRにプッシュしたい
  • awsコマンドで、ECSの操作を行いたい
  • frontディレクトリ内で、webpackのビルドを行い、その出力ファイル(index.htmlとその他staticファイル)をphalcon(webアプリケーション)ディレクトリ内のpublicディレクトリ内にブッコミたい

これを実現するには、以下の課題をクリアする必要がある

  • npmのインストール
  • dockerのインストール
  • awsコマンドのインストール

調査

gitlabCIについて一つ勘違いしていた。てっきりprivateなサーバーでのみ動かすことしかできないと思っていたが、どうやらGitlabが用意しているCIサーバーも制限があるが存在しているようである。自前サーバーで動かすのをSpecific Runnersというのに対しShared Runnersというらしい。1ヶ月1グループあたり2000回まで無料のようである。太っ腹。参考元

さらにさらに、どうやらimageを指定して、その中で動作するらしい。Dockerは新世界の神ではないか。
細かいCIの設定は.gitlab-ci.ymlに以下のようなフォーマットでかく。以下は最小構成である、
script以下に、複数のコマンドを書くことができる。また、stageは複数定義可能であるが、コンテナの状態が引き継がれないので、基本的に1stageで行なっている

image: python:2.7

stages:
  - deploy

deploy_job:
  stage: deploy
  script:
    - XXXXXXXXXXXX

awsコマンド

先ほどの、npm,docker,awsの中でインストールがめんどくさそうなのはawsという直感を元にpython:2.7イメージを使用。デフォルトでawsコマンドが使えるので。python:2.7はDebianのjessieがベースになっているとのこと。

ここで、みんな大好きAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYを環境変数に登録する。.gitlab-ci.ymlに書くと、gitに追跡されてしまうので、ここはgitlabの設定であらかじめ登録しておくこと

スクリーンショット 2018-05-15 0.14.16.png

ここまでで.gitlab-ci.ymlは以下のようになった

image: python:2.7

stages:
  - deploy

deploy_job:
  stage: deploy
  script:
    - pip install --upgrade pip
    - pip install --upgrade awscli

npm

フロントエンドには、vueを使っているが、webpackでビルドする必要がある。

無論python:2.7に入っていないので自力で導入。

以下を、install_npm.shとして作成

curl -sL https://deb.nodesource.com/setup_10.x |  bash -
apt-get install -y nodejs

これを踏まえて、gitlab-ci.ymlは以下のようになる

image: python:2.7

stages:
  - deploy

deploy_job:
  stage: deploy
  script:
    - pip install --upgrade pip
    - pip install --upgrade awscli
    - sh ./ci/install_npm.sh
    - cd ./front
    - npm install
    - npm run build

docker

ECSで動かすタスクで動くDockerイメージを更新するには、ECSというdockerリポジトリに、新たにプッシュする必要がある。

ぐぐるとよく出てくる方法はめっちゃ長かった。
1. 古いdockerをアンインストール
2. 周辺パッケージをインストール
3. GPG鍵の取得
4. .......以降省略

ダメ元でdocker公式読んだら、もっと簡単な方法があった。やはり公式が正義

curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

これだけでいいとのこと。あっさり。

しかし、これだけでは、プロセスが停止したままなので、service docker startを加えて以下が最終形。install_docker.shとしてファイル作成

curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
service docker start

これでdockerがすぐに動かせる状況になった

ECRにプッシュ

プッシュするタグ名は、複数箇所で使用するので、以下のように環境変数として定義。これはシークレットレベルは低いので、.gitlab-ci.ymlに定義

deploy_job:
  stage: deploy
  variables:
    TAG_NAME: XXXXXXXXXXXX
  script:
(略)
    - aws_var=`aws ecr get-login --no-include-email --region ap-northeast-1 `
    - $aws_var
    - docker build -t kyujin .
    - docker tag kyujin:latest $TAG_NAME
    - docker push $TAG_NAME

ECSを更新

最後にして最難関。愚直にやろうと思うと以下の手順でやる必要がある

  1. タスク定義を先ほどプッシュしたイメージを含んで更新(リビジョン)
  2. クラスター内のサービスを更新

非常にめんどくさい。CodePipelineならGUIでサクッとできたのでこちらは地獄のように感じる

以下のスクリプトを使わせてもらった。

https://github.com/silinternational/ecs-deploy

ecs_deploy.shとしてファイルを作成し、以下で実行。

sh ./ci/ecs_deploy.sh -r $REGION -c $CLUSTER -n $SERVICE -i $TAG_NAME -t 1800

これだけで12も自動でやってくれる。幸せ。

しかし、shでやってると怒られた

./ci/ecs_deploy.sh: Syntax error: "(" unexpected

どうやら、Debianでshをすると、dashが起動する影響らしい。微修正

./ci/ecs_deploy.sh -r $REGION -c $CLUSTER -n $SERVICE -i $TAG_NAME -t 1800

jsonのパーサーのjqも必要なのでサクッとインストール

apt-get install jq

結論

最終形は以下のようになった。めでたしめでたし。

image: python:2.7

stages:
  - deploy

deploy_job:
  stage: deploy
  variables:
    TAG_NAME: XXXXXXXXX
    REGION: YYYYYYYY
    CLUSTER: ZZZZZZZZZZZZZZZZ
    SERVICE: WWWWWWWWWWWWW
  script:
    - pip install --upgrade pip
    - pip install --upgrade awscli
    - sh ./ci/install_docker.sh
    - sh ./ci/install_npm.sh
    - cd ./front
    - npm install
    - npm run build
    - cd ./../
    - apt-get install jq
    - aws_var=`aws ecr get-login --no-include-email --region ap-northeast-1 `
    - $aws_var
    - docker build -t kyujin .
    - docker tag kyujin:latest $TAG_NAME
    - docker push $TAG_NAME
    - chmod 777 ./ci/ecs_deploy.sh
    - ./ci/ecs_deploy.sh -r $REGION -c $CLUSTER -n $SERVICE -i $TAG_NAME -t 1800

所管

  • 日曜の午前3時には、masterプッシュして30秒後にはCIが走ってたが、月曜の今現在、masterプッシュして30分経っても走らずにPending状態。。。。やっぱり共有している以上、しかたないのか。。、。
  • 趣味でやるぶんにはCI用意してくれるだけで御の字
  • gitlabのドキュメント、日本語対応してくれんかなあ
diggy-mo
クソ雑魚エンジニア
https://blog.morifuji-is.ninja/
atma_inc
Change the common sense with algorithm を達成するためのスタートアップ
https://atma.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした