GitLabのトークン

GitLab Token
– Personal Access tokens
— GitLab API, GitLab repository, GitLab registry
– OAuth2 token
— OAuth2 ProviderとしてOAuth認証
– Impersonation tokens
— Personal access tokensの特殊な形
– Project access tokens
— Project単位のPersonal access tokens
– Deploy tokens
— git clone及びGitLab管理下のpackageとcontainer registryへのpush/pullを可能にする
– Deploy keys
— repositoryのread-onlyまたはread-writeのみ可能とする
  – projectのowner/maintainerが発行可能でcloneしてくるのに有用
– Runner registration token
— GitLabRunnerをGitLab側に登録する際に認証するためのtoken
— CI/CDのjobを実行するRunnerを紐付ける
– Runner authentication token
— GitLabRunnerの認証登録後にRunnerが入ったホストに登録されるtoken
— config.toml内に自動登録される
– CI/CD Job token
— CI/CD job実行時のAPI利用の際に認証に使用される一時的なtoken
— job内でrepositoryをclone, pushなどをする際に、CI_JOB_TOKENとして予め環境変数に定義されているものを即座に利用可能

なるほど
docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
これだと、gitlab-ci-tokenはCI/CD job tokenのことか

GitLab runner CI/CD

GitLab Runner: GitLabでコミットを検知してGitLab Runnerがジョブを実行、ジョブの結果がGitLabから確認できる

### Shared RunnersとSpecific Runners
Shared Runnersはプロジェクトを跨いで共有、Specific Runnerはプロジェクトに紐づけて専用利用

### Executer
ジョブの実行形式
Shell, Docker, Docker Machine, Parallels, VirtualBox, SSH, Kubernetes
-> shellであればGitLab Runnerがインストールされたホスト上でBash等のShellベースでジョブを実行

### パイプライン
パイプライン方式でジョブを実行する

image: python:3.6.5
variables:
  S3_BUCKET: デプロイに使うS3バケット
  AWS_DEFAULT_REGION: ap-northeast-1
unittest:
  stage: test
  script:
    - pip install pytest
    - pip install -r requirements.txt
    - python -m pytest tests/ -v

deploy:
  stage: deploy
  script:
    - pip install awscli
    - pip install -r requirements.txt -t hello_world/build/
    - cd hello_world/*.py hello_world/build/
    - aws cloudformation package --template-file template.yaml --output-template-file output.yaml --s3-bucket ${S3_BUCKET}
    - aws cloudformation deploy --template-file output.yaml --stack-name demo --capabilities CAPABILITY_IAM

重要なのはdeployのところか
なるほど、testも理解しておかないとあかんな…

devブランチにpushされたら…
masterブランチにpushされたら… など設定できる

– service: 対象のジョブ実行中に起動するDockerイメージ, scriptsを実行するためのDockerイメージ servicesで指定されたコンテナはimagesで指定されたコンテナとは別で起動
– only: 対象ジョブの実行を特定のブランチや特定のタグがプッシュされた時に限定することがd系る
– artifact: ジョブの成果物としてジョブを跨いで共有できる
– when: ジョブを実行するタイミング 
L on_success, on_failure, always, on_failure
– environment: 対象のジョブがどの環境へデプロイを行うのか定義できる

なるほど、そろそろ実際にやってみるか

gitlab入門

stage: パイプラインを制御するためのもので、job毎に使用できるステージを定義するもの。dependenciesとセットになる同じステージのjobは並行で実行される

artifacts: 成果物のパスを指定。特定のjobから成果物をDLできる。後続のjobで引き継がせることができる。ディレクトリのみ。

image: sample.gitlab.com/vagrant/sample/app
stages:
  - test
  - build_static
rspec:
  stage: test
  services:
    - mysql:5.7
  variables:
    MYSQL_DATABASE: sample_test
    MYSQL_ROOT_PASSWORD: mysql_strong_password
  before_script:
    - "echo \"install: --no-document\" > ~/.gemrc"
    - "echo \"update: --no-document\" > ~/.gemrc"
    - bundle install --jobs=4
    - buncle exec rake db:setup RAILS_ENV=test
    - buncle exec rake db:migrate RAILS_ENV=test
  script:
    - bundle exec rspec
  artifacts:
    paths:
      - coverage/

pages:
  stage: build_static
  dependencies:
    - rspec
  script:
    - my coverage/ public/
  artifacts:
    paths:
      - public
    only:
      - master

どのようなjobを実行するか設計 -> jobの集合体をstage
commitするとjobが実行される
build, test, docker_build

stages:
  - build
  - test
  - docker_build

# 全ジョブの前処理
before_script:
  - chmod +x ./gradlew
  - export GRADLE_USER_HOME=`pwd`/.gradlew

# 実行するジョブ
build:
  stage: build
  image: java:openjdk-8u111-jdk-alpine
  script:
    - ./gradlew assemble
  artifacts:
    name: "${CI_PROJECT_NAME}_${CI_COMMIT_REF_NAME}"
    paths:
      - build/libs/*.jar

test:
  stage: test
  image: java:openjdk-8u111-jdk-alpine
  script:
    - ./gradlew test sonarqube -PsonarBranch=$CI_COMMIT_REF_NAME -PsonarHostUrl=$SONAR_HOST_UR+

docker_build:
  stage: docker_build
  image: docker:18.03
  script:
    - docker login -u "gitlab-ci-token" -p "$CI_JOB_TOKEN" $CI_REGISTRY
    - docker build --build-arg JAR_FILE=$(find ./build/libs/ -name "sample*.jar") -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME" ./
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"

うーん、なるほど、少しずつって感じやな

gitlab tips

### Services: コンテナイメージを複数扱う
servicesというキーワードを用いると、ベースイメージと接続可能なコンテナを定義できる

servies:
  - postgres:latest
variables:
  POSTGRES_DB: custom_db
  POSTGRES_USER: ucstom_user
  POSTGRES_PASSWORD: custom_password

### Anchors

test1:
  stage: test
  image: python:latest
  before_script:
    - pipenv install --dev --system
  script:
    - pytest test1

test2:
  state: test
  image: python:latest
  before_script:
    - pipenv install --dev --system
  script:
    - pytest test2
.test_template: &test_definition
  state: test
  image: python:latest
  before_script:
    - pipenv install --dev --system

test1:
  <<: *test_definition
  script:
    - pytest test1

test2:
  <<: *test_definition
  script:
    - pytest test2  

### 用意されているGitlab変数

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
  script:
    - docker build --pull -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
  only:
    - tags

### only and except
tagがpushされた時のみ
only:
– tags
ブランチがpushされた時は実行しない
except:
– master

あれ、Dockerfileではなく、gitlab.ymlにimageを書くの?

gitlab-ci.yml練習

stages:
  - prepare
  - echo

prepare-job:
  stage: prepare
  script:
    - echo "Prepare bofore echo"

echo-job:
  stage: echo
  script: 
    - echo "Ahoy! This is Gitlab CI/CD!"

stages:
  - dev
  - stg

dev-job:
  stage: dev
  script:
    - echo "Hello, $GITLAB_USER_LOGIN!"
    - echo "This is $CI_COMMIT_BRANCH branch."
    - sleep 5

stg-job:
  stage: stg
  script:
    - echo "hello world!"

$GITLAB_USER_LOGIN, $CI_COMMIT_BRANCH branchは予め用意されている模様

### Docker

default:
  image: ruby:2.7.2

stages:
  - stg

hello-job:
  stage: stg
  script:
    - ruby -v

### artifact

stages:
  - dev

generate-file:
  stage: dev
  artifacts:
    paths:
      - hoge.txt
  script:
    - echo hoge > hoge.txt

なるほど、なんか色々できそうなことはわかった

GitLab Container Registryを使おう

registoryにログインします
$ sudo docker login registry.gitlab.com
Login Succeeded

Dockerfile

FROM alpine:latest

### build
$ sudo docker build -t registry.gitlab.com/hpscript/docker .
$ sudo docker images;
registry.gitlab.com/hpscript/docker latest 9c842ac49a39 41 hours ago 5.57MB
$ sudo docker push registry.gitlab.com/hpscript/docker

なるほどー、なんか勉強になるな

[Docker Hub] イメージを登録する

1. リポジトリを作成する
ddddocker/myexample

2. Dockerイメージ名を調整する
$ sudo docker tag myphpimage ddddocker/myexample:v1

3. リポジトリログイン
$ sudo docker login

4. イメージ登録
$ sudo docker push ddddocker/myexample:v1

なるほど、なんとなく基礎はわかってきた。
あとはdockerfileのベストプラクティスとデプロイCI/CDのところか...

[Docker] イメージの保存と読み込み

– 作成したイメージをファイル化すると、別のコンピュータに持っていくことができる。
– ファイル化にはdocker saveを使う。
– ファイルから取り出すには docker loadを使う。

### docker saveでイメージからファイル化
$ sudo docker save -o saved.tar myphpimage
$ ls -al saved.tar
-rw——- 1 root root 262609920 Mar 24 07:19 saved.tar

内容確認
$ sudo tar tvf saved.tar

### docker loadする
$ sudo docker image rm myphpimage
$ sudo docker load -i saved.tar
$ sudo docker image ls
$ sudo docker stop myphp02
$ sudo docker rm myphp02


export/importによるファイル化
L コンテナ情報が失われるためあまり使用しない

なるほど、Docker hubなどを使わなくても、tarファイルに出来るんだね
中々勉強になるわ…

[Docker] コマンドの実行

コマンドの実行系統の命令は「RUN」「CMDとENTRYPOINT」の2種類ある
前者はイメージ作成時、後者はコマンドの実行時

### RUN
RUNコマンドはdocker buildするタイミング
(1)シェル形式
/bin/sh -cを経由してコマンドが実行
RUN ${コマンド} ${引数} …

(2)exec形式
実行したいコマンドや引数を[]を囲んで記述
RUN [“コマンド”, “引数”, …]

RUNコマンドごとにレイヤーが増えるので、一つのコマンドで実現できる様にする
RUN コマンド1 && コマンド2 && コマンド3

ONBUILD COPY コピー元 コピー先

### CMDとENTRY POINT
コンテナを起動したときのタイミングでコンテナの中で実行するコマンドを指定する
(1)ENTRY POINT: コマンドの指定を強要する。イメージの利用者はこの設定を変更することはできない。
docker runの最後に指定するコマンドは、ENTRYPOINTで指定したコマンドへの引数となる

(2)CMD
docker runの際に指定する最後のコマンドのデフォルト値を変更

殆どの場合、CMDが使われる
イメージが通信しようとするポート番号はEXPOSEで指定する

### HTTPDのDockerfile
https://github.com/docker-library/httpd/blob/master/2.4/Dockerfile

phpimage/index.php

<body>
	Your IP <?php echo $_SERVER['REMOTE_ADDR']; ?>。
</body>

Dockerfile

FROM debian
EXPOSE 80
RUN apt update \
&& apt install -y apache2 php libapache2-mod-php \
&& apt clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm /var/www/html/index.html
COPY index.php /var/www/html
CMD /usr/sbin/apachectl -DFOREGROUND

apt clean, rm -rf /var/lib/apt/lists/* でパッケージを削除する。常套句。
中間ファイルを削除することで、Dockerイメージのサイズを小さくできる
CMD /usr/sbin/apachectl -DFOREGROUND でapacheをフォアグラウンドで実行する

$ sudo docker build . -t myphpimage
$ sudo docker images;
REPOSITORY TAG IMAGE ID CREATED SIZE
myphpimage latest 5c4aa75b77ce 4 minutes ago 254MB

– コンテナを動かす
$ sudo docker run -dit –name myphp -p 8080:80 myphpimage

キャッシュを活用するとビルドを高速化できる
キャッシュを使わない場合は、docker build . -t myphpimage –no-cache とする

なるほど、Dockerfileの作成は練習が必要だな…