14
22

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 5 years have passed since last update.

Gitlab(Runner、Container Registry)+AnsibleでローカルにCI環境を作ってみる

Last updated at Posted at 2018-08-22

概要

Gitlab、Gitlab Runner、Gitlab Container Registry、AnsibleでCI環境をローカルに作ってみます
上記のすべての環境はDockerコンテナで扱っていきますので、予めDockerの導入をしてください
なお、デプロイはGitlab Runner以外でも利用できるAnsibleを採用しています

当記事でCIの一通りの流れを体験できれば幸いです
コードの解説は最後にまとめてやります

参考:Ansible勉強&実践結果(随時更新)

実行環境

Docker for Windows 18.06.0-ce

大まかな全体の流れ

  1. Gitlabプロジェクトを作成する
  2. GitlabとGitlab Runnerの連携設定
  3. サンプルアプリケーションのリポジトリルートに「.gitlab-ci.yml」ファイルを作成し、Gitlabにプッシュする
  4. Gitlab Runnerで.gitlab-ci.ymlに定義されたジョブの実行条件(ブランチ名、タグ名)でタスクが実行される
    ※.gitlab-ci.ymlのリファレンスは以下を参照ください
  5. Gitlab Runnerでビルドされたアプリケーションイメージ(Node.jsのアプリ)をDocker RegistryにPushする
  6. Ansible経由でRegistryからアプリケーションイメージを取得し、デプロイする

※gitlabユーザはすべてrootユーザで実行します

structure.png

環境作成

環境作成はこちらのソース(github.com/comefigo/docker-gitlab-ci)で作成します
以下のコンテナが立ち上がります

  • Gitlab
  • Gitlab Runner(Ansibleやpipなどが導入されています)
  • Docker Registry(Docker Image Private Registry)
  • Docker Registry frontend(Docker RegistryをGUIで参照するWebアプリケーション)
> docker-compose up -d

Creating gitlab-registry ... done
Creating gitlab          ... done
Creating gitlab-runner      ... done
Creating gitlab-registry-ui ... done

Gitlab

  1. rootアカウントのパスワードを設定
  2. デフォルト管理者ユーザ「root」と1.で作成したパスワードでログインできることを確認
  3. ssh鍵登録でソースをプッシュできるように公開鍵を登録
    鍵の生成手順はこちらを参照してください

Gitlab Runner

runnerでDockerイメージをビルドするため、docker.ioをインストールしています
ホストのdockerソケット(/var/run/docker.sock:/var/run/docker.sock:ro)を読み取り専用でマウントし、runnerコンテナからホストのdockerソケットを通してホストのDockerを操作する
もし、ホストのDockerと分離したい場合は、docker in dockerを利用してください(後述のDocker Runnerの設定で設定変更が必要になります)

参考:Docker for Windowsでコンテナ内でDocker(dind)を使う

dockerfile
FROM gitlab/gitlab-runner:latest

# update libs
RUN apt-get update \
    && apt-get -y upgrade \
    && apt-get install sudo

# add sudo user
RUN echo '%gitlab-runner ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/gitlab-runner

# install python libs
RUN apt-get install -y python3 build-essential python-dev docker.io

# install pip
RUN curl -kL "https://bootstrap.pypa.io/get-pip.py" | python

# install aws cli
RUN pip install awscli ansible boto boto3 docker-py
docker-compose.yml
~省略~
  gitlab-runner:
    build: 
      context: ./runner
      dockerfile: Dockerfile
    image: gitlab-runner
    container_name: gitlab-runner
    hostname: gitlab-runner
    restart: always
    volumes:
      - gitlab-runner-conf:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock:ro
    env_file:
      - envs/common.env
      - envs/registry.env
    depends_on:
      - gitlab

Container Registry

Container Registryを有効化するためにGitlabの設定ファイル(/etc/gitlab/gitlab.rb)の以下の項目を有効化しています
これらの設定項目は環境変数GITLAB_OMNIBUS_CONFIGを通じて直接設定できるので、gitlab.rbを直接編集する必要はない
なお、registry_hostはgitlab-registry(コンテナ名)にしていますが、このサンプル環境ではすべてのコンテナが同一ネットワーク内にあるため、ホスト名=コンテナ名にしています。ただし、Dockerホスト側からは見えないので、後述ではhostsに登録しています

SSL通信など詳しい設定方法はこちらを参照してください

docker-compose.yml
~省略~
  gitlab:
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        gitlab_rails['registry_enabled'] = true
        gitlab_rails['registry_host'] = "gitlab-registry"
        gitlab_rails['registry_port'] = "5000"
        gitlab_rails['registry_api_url'] = "http://gitlab-registry:5000"

動作確認

  1. Gitlabでbusyboxという名のプロジェクトを作成してください

  2. 「Container Registry」が有効になっていることを確認
    busybox_project.png

  3. Dockerのホストマシンでホスト名を追加
    Registryのホスト名(gitlab-registry)をDNSに登録していないため、ホストマシンから見た場合はlocalhostになるので、ホスト名gitlab-registryを逆引きできない。なのでホストマシンのhostsファイルに以下のように追加します

    hosts
    127.0.0.1 gitlab-registry
    
  4. Dockerイメージの取得
    テスト用に軽量のbusyboxイメージを使用します

    > docker pull busybox:latest
    
  5. イメージのタグ付け
    docker tag <イメージ名>:<イメージタグ> <レジストリ名>:<ポート番号>/\/<プロジェクト名>:<イメージタグ>

    > docker tag busybox:latest gitlab-registry:5000/root/busybox:latest
    
  6. RegistryにPush
    Registryに認証を追加していないため、docker loginは不要

    > docker push gitlab-registry:5000/root/busybox:latest
      The push refers to repository [gitlab-registry:5000/root/busybox]
      f9d9e4e6e2f0: Pushed
      latest: digest: sha256:5e8e0509e829bb8f990249135a36e81a3ecbe94294e7a185cc14616e5fad96bd size: 527
    
  7. 確認
    PushしたDockerイメージが表示されていることを確認
    busybox_regisrty.png

CI体験

1. プロジェクトを作成

「myapp」という名のプロジェクトを作成してください

2. Gitlab RunnerとGitlabの連携

gitlab-runnerの登録の詳細はこちらを参照してください

  1. Runnerの登録

    > docker exec -it gitlab-runner gitlab-runner register
    
  2. Gitlab URLの入力
    URLはgitlabのコンテナ名を使用する

    Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
    > http://gitlab/
    
  3. Tokenの登録
    「myappプロジェクト」-「Settings」-「CI/CD」-「Runners」-「Specific Runners」の「Use the following registration token during setup:」のTokenを以下に入力

    Please enter the gitlab-ci token for this runner:
    > ********
    

gitlab-runner-token.png

  1. Runnerの説明
    Runnerの用途がわかるような説明を入力

    Please enter the gitlab-ci description for this runner:
    > gitlab ci demo
    
  2. タグ付け
    Runnerのタグによって、後述の.gitlab-ci.ymlでタスクの実行を振り分けることができる
    例えば、ソースコードビルド用、Dockerイメージのビルド用、デプロイ用にそれぞれタグ異なるタグを付与し、実行先を分ける

    Please enter the gitlab-ci tags for this runner (comma separated):
    > ci
    
  3. 実行モードの選択

    Please enter the executor: docker+machine, docker-ssh+machine, docker, docker-ssh, shell, ssh, parallels, virtualbox, kubernetes:
    > shell
    
  4. 登録確認
    activedのRunnerが登録されていることを確認

gitlab-runner-active.png

3. ビルド用の変数を設定

gitlab-ciのタスク実行時に外部変数として渡すことができます
これを用いることで秘密鍵なども安全に渡すことができる
今回はアプリケーションのバージョンを渡せるようにキー:APP_VERSION、値:1.0.0を作成します
gitlab_project_variables.png

4. サンプルソースをプロジェクトにPush

サンプルソース「docker-gitlab-sample-app」をローカルにCloneし、gitlabのmyappにすべてのブランチ(master/dev)をPushしてください

※gitリモートのURLは「git@localhost:root/myapp.git」になります!
※当サンプルソースは簡単なNode.jsのWebアプリケーションになります
※サンプルソースでは30003001ポートを使用しますので、既に使用している場合は停止するか、.gitlab-ci.yml内のapp_portを変更してください

5. CI/CDの確認

ブランチにプッシュされ次第、.gitlab-ci.ymlに定義されたタスクが実行される
「myapp」-「CI/CD」-「Pipelines」で各ブランチのタスクが実行されることを確認
gitlab_ci_pipeline.png

6. サンプルアプリの動作確認

CI/CDでpipelineの実行が成功したら、サンプルアプリの動作を確認しましょう
myapp-masterが本番用、myapp-devが開発用と想定
Dockerホストで以下のようにサンプルアプリが実行されていることを確認できます

> docker ps

CONTAINER ID        IMAGE                                      COMMAND                  CREATED              STATUS                    PORTS                                             NAMES
9ea9cb4af7df        gitlab-registry:5000/root/myapp:1.0.0      "/bin/sh -c 'node ap…"   About a minute ago   Up About a minute         0.0.0.0:3001->3001/tcp                            myapp-dev
59af2fe4858d        2ccdc5dd94c7                               "/bin/sh -c 'node ap…"   5 minutes ago        Up 5 minutes              0.0.0.0:3000->3000/tcp                            myapp-master

ブラウザで「http://localhost:3000 」、「http://localhost:3001 」をそれぞれ確認してください
sample_app_master.png
sample_app_dev_1.0.0.png

7. アプリケーションのバージョンアップ

仮にアプリケーションのバージョン1.0.1を開発すると想定しましょう
まず、前述で作成した変数「APP_VERSION」を「1.0.1」に更新してください
※「Reveal value」ボタンを押せば、値を更新できます

gitlab_update_variables.png

8. アプリケーションの修正

サンプルソースのブランチをdevに切り替え、app.jsを適当に変更して、コミットとgitlabにプッシュしてください
CI/CDが問題なく終了したら、「http://localhost:3001 」を確認してください
myapp-masterはver.1.0.0のままであることも確認してください
sample_app_dev_1.0.1.png

9. 本番適用

「dev」から「master」にマージリクエストを作成し、マージしてください
CI/CDが実行され、問題なく終了したら、「http://localhost:3000 」を確認してください

※green/blueデプロイとかオシャレなことしていないので、プッツンと一回切れますので、ご了承ください

10. Container Registryの確認

ビルドしたAPPイメージがContainer Registryで登録されていることを確認

gitlab_myapp_registry.png

コード解説

.gitlab-ci.yml

  • stagesに定義されている順(build → deploy)に処理が実行されます
  • tagsはGitlab Runnerの登録時に設定したタグを指定(指定しないと動きません)
  • $APP_VERSIONは前述で設定したmyappプロジェクトの変数になります
  • $ENV_DOCKER_REGISTRY_HOSTと$ENV_DOCKER_REGISTRY_PORTはgitlab-runnerコンテナの環境変数としてregistry.envを読み込んでいます
  • ブランチごとにタスクを分離させていて、Ansibleのタスク実行時にAnsible内の変数を上書きするように--extra-vars=を設定しています
  • デプロイ先をローカル(-i inventories/hosts_local)にしていますが、デプロイ先に応じてインベントリファイルを変更することもできます
    例:
     devブランチのタスクに ansible-playbook -i inventories/hosts_develop xxxxx
     masterブランチのタスクに ansible-playbook -i inventories/hosts_production xxxxx
  • dockerコマンドはsudoで実行している
    前述でマウントしたdocker.sockにはroot権限しか操作できない(変更できない)ため、gitlab-runnerユーザが実行する際にはsudoが必須になります
.gitlab-ci.yml

stages:
  - build
  - deploy

# Docker イメージのビルド&レジストリに追加
build:
  stage: build
  tags:
    - ci
  script:
    - sudo docker info
    - sudo docker build -t myapp:$APP_VERSION ./
    - sudo docker tag myapp:$APP_VERSION $ENV_DOCKER_REGISTRY_HOST:$ENV_DOCKER_REGISTRY_PORT/root/myapp:$APP_VERSION
    - sudo docker push $ENV_DOCKER_REGISTRY_HOST:$ENV_DOCKER_REGISTRY_PORT/root/myapp:$APP_VERSION

# devブランチにマージされたら以下のタスクを実行する
deploy_dev:
  stage: deploy
  tags:
    - ci
  script:
    - env
    - ansible --version
    - 'cd ./ansible && ansible-playbook -i inventories/hosts_local deploy.yml --extra-vars="{\"all\": { \"app_name\": $CI_PROJECT_NAME-$CI_BUILD_REF_NAME, \"app_version\": $APP_VERSION, \"docker_register_url\": $ENV_DOCKER_REGISTRY_HOST, \"docker_register_port\": $ENV_DOCKER_REGISTRY_PORT, \"app_port\": 3001 }}"'
  only:
    - dev

# masterブランチにマージされたら以下のタスクを実行する
deploy_production:
  stage: deploy
  tags:
    - ci
  script:
    - env
    - ansible --version
    - 'cd ./ansible && ansible-playbook -i inventories/hosts_local deploy.yml --extra-vars="{\"all\": { \"app_name\": $CI_PROJECT_NAME-$CI_BUILD_REF_NAME, \"app_version\": $APP_VERSION, \"docker_register_url\": $ENV_DOCKER_REGISTRY_HOST, \"docker_register_port\": $ENV_DOCKER_REGISTRY_PORT, \"app_port\": 3000 }}"'
  only:
    - master

ローカル以外の環境にデプロイしたい場合は、以下のファイル(hosts_production/hosts_develop)を修正するのと.gitlab-ci.ymlのansible-playbookで指定するインベントリファイルを変更してください

ansible/inventories/hosts_production
[prd]
dev1 ansible_host=127.0.0.1

[prd:vars]
ansible_user=<SSHユーザ>
ansible_ssh_private_key_file=<SSH鍵のパス>

all.yml

ansibleの変数ファイルになります
ansible-playbookコマンドで変数の上書きがなければ、ここの変数の値が使われる

all.yml

all:
  app_port: 3000
  app_version: "0.0.1"
  app_name: myapp
  docker_register_url: "gitlab-registry"
  docker_register_port: 5000
14
22
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
14
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?