LoginSignup
1

More than 3 years have passed since last update.

GithubにGoで書いたDockerをTravisでCIする

Last updated at Posted at 2019-08-27

あまり他人のソフト使うのが上手くないので、色々とハマりポイントがあったもので
Git履歴よりハマりポイントのおさらい

目指すもの

GithubにTravisCIを連携させることで、PushやPullRequestした時などに
自動的にTestやLintを行い、コードカバレッジを行う事ができる
大手の開発では一般的なスタイルではなかろうか?

個人的に勉強ついでに作っていた SlackBotのプログラムを使って勉強してみた

SlackBotである。プラグインを入れる事で機能拡張を行う事ができる
とりあえず勉強用テストプロジェクトである
これからリファクタリングしたり interface化して、LintなりTestなり色々な改造を行う予定
(現在 gomodule導入テストのためプラグインもecho以外動かないはず)

dockerファイルを修正

今までDockerfileにて go buildして実行ファイルを起動させていたが
TravisやローカルでTestをまわすために
また、コード修正のたびに docker-compose buildしたくないので
Dockerでは何もせず、シェルスクリプトでビルド実行やテストを行うように変更した

Dockerファイル

dockerfile
WORKDIR /build
COPY src .
CMD ./build.sh
CMD ls

CMD ./GOSICK

この辺りを削除した。ぶっちゃけ Goのイメージそのまま使うのでDockerfileは不要で
docker-composeにimage指定するだけでいいけど
今後なにかインストールする可能性もあるので Dockerファイルはのこした

build.sh

今回はプラグインのビルドなども入るので、ワンライナーで書かず
ビルドをシェルスクリプトでわけたかった
(最終的にはMakefile等にしたいなあ)

build.sh
if [ $TEST = "test" ]; then
    cd plugins/echo
    go test -v ./... --buildmode=plugin
    cd ../..

    go test -v ./...
else
    cd plugins/echo
    go build --buildmode=plugin
    cd ../..

    go build
fi

テストと通常ビルドを分けるため $TEST環境変数で分けることにした

Script

docker_app_build
docker-compose up -d
docker-compose exec gosick_app bash -C '/app/build.sh'
docker_app_test
docker-compose up -d
docker-compose exec -e TEST=test gosick_app bash -C '/app/build.sh'

テストと実行でファイルを分けたが、環境変数以外はかわらないので、まとめてもいいなあ
docker-compose up も別にすべきかなあ

等色々考えているが、しばらく使って考える予定

GithubにTravisを連携させバッヂをつける

例えばこの辺を参考に、バッヂまでつける

Travisの設定

とっても苦労したTravisの設定
とりあえずはどのリポジトリをPushしても通知が入るようにしている
プロジェクトのルートに .travis.yml ファイルを作成してPush

最初の設定

.travis.yaml
sudo: required

services:
  - docker

before_install:
#  - docker-compose up -d

install:

before_script:

script:
  - scripts/docker_app_run
 # - docker-compose exec golang go test -v ./...

after_script:

notifications:

いろんなサイトをみて上記の設定ファイルを書いたが、色々なエラーが出てダメ
なので色々と

language設定

TravisのページをみるとRubyと判断されていたのでlanguageを設定

.travis.yaml
language: go

ただ、Goのバージョンが古かったのでちゃんとバージョン指定してみた

.travis.yaml
language: go
go: 
  - 1.12.x

GO111MODULE

ログをみていると GO111MODULE=autoになっていた
今回はgo module使いたいので onにしたいので下記のようにかいてみた

.travis.yaml
script:
  - env GO111MODULE=on scripts/docker_app_test

ところがログをみても GO111MODULE=autoのままだった

どうやらenvセクションに書く必要があった

.travis.yaml
env:
  - GO111MODULE=on

go_import_path

githubのアドレスを加えた

.travis.yaml
go_import_path: github.com/YukiMiyatake/GOSICK

スクリプトパーミッション

Windowsで開発を行っていたため、ファイルのパーミッションがおかしくなっていた
Travis内でパーミッションを設定してもいいが、根本的な解決としてスクリプトファイルにパーミッションをあたえPushした

この辺をみて、パーミッションを正しく設定したら動いた

DockerComposeのバージョンが古い

docker-composeのバージョンが古かったので念のためバージョンアップを行った

まず、TravisのDockerやDockerComposeバージョンは例えば下記で調べられる

.travis.yml
before_install:
  - docker-compose -v
  - docker -v

これによると

$ docker-compose -v
docker-compose version 1.17.1, build 6d101fb
before_install.3
$ docker -v
Docker version 17.09.0-ce, build afdb6d4

Dockerはとりあえず今回はバージョンはいいとします
DockerComposeだけ 1.24.1にバージョン上げます

.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1

before_install:
  - sudo rm /usr/local/bin/docker-compose
  - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
  - chmod +x docker-compose
  - sudo mv docker-compose /usr/local/bin

Travis公式のドキュメント通りです。

ところが色々不可解なエラーが出ます

Yamlの罠

yamlじたいほとんど書かないのでよくわかってませんが、気になるポイントをみつけた

.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1

結論からいうと

GO111MODULE:on
だとGO111MODULEは定義されずautoになる

GO111MODULE: on
だとGO111MODULEはtrueが定義されてしまう

GO111MODULE= on
だとGO111MODULEは空文字が定義される

よって
GO111MODULE=on

以外はダメ

DOCKER_COMPOSE_VERSION = 1.24.1
DOCKER_COMPOSE_VERSION:1.24.1
DOCKER_COMPOSE_VERSION :1.24.1
は共に定義されない

DOCKER_COMPOSE_VERSION: 1.24.1
DOCKER_COMPOSE_VERSION=1.24.1
はOK

:の場合は前にスペースNG、後ろにスペース必須
=の場合は 前も後ろもスペースNG
GO111MODULEには=しか使えない
DOCKER_COMPOSE_VERSIONは上記ルールを守っているなら:でも=でもOK

細かい事はおいといて

.travis.yml
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1

とするとちゃんと定義されるようになった

並列実行問題

.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1

で両方の環境変数は定義されたが、なぜか2つ実行されているっぽい
その2つの環境変数は

GO111MODULE=on, DOCKER_COMPOSE_VERSION定義なし
GO111MODULE定義なし, DOCKER_COMPOSE_VERSION=1.24.1

の2つ
どう考えても並列実行されている
ドキュメント見た感じだと globalに設定すればよさそう

.travis.yml
env:
  global:
    - GO111MODULE=on
    - DOCKER_COMPOSE_VERSION=1.24.1

これで、すべての実行環境において上記のフラグが立つようになった
今回は使用していないが metrix: に環境変数配列を列挙すると並列で実行できるので
テストの高速化を行う時は使ってみよう
(ただし無料版だとたぶん2並列までしかできない)

DBのbind問題

下記の謎エラーが出て結構悩まされた

ERROR: for gosick_mysql  Cannot start service gosick_mysql: driver failed programming external connectivity on endpoint gosick_mysql (cb76f17f3761214c04ca3c4ca03fe4b993e65b0ca14b76b711606651d40c8a8c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: for gosick_mysql  Cannot start service gosick_mysql: driver failed programming external connectivity on endpoint gosick_mysql (cb76f17f3761214c04ca3c4ca03fe4b993e65b0ca14b76b711606651d40c8a8c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use

BindAddressが使われている。3306なのでMySQLが既に立ち上がっているようだが、いくら見渡してもそれらしいものがない・・
ので困った
MySQLのDockerは今は使ってないので消せば解決はするが、ちゃんと解決させたいので調べたら、まさかの! TravisでMySQLが立ち上がっていた・・・

ので、実行前にTravisのMySQLを落とす

.travis.yml
before_install:
  - sudo /etc/init.d/mysql stop

やった!できた!

まとめ

色々な罠があったが、とりあえずTravisCIを動かすことができた
一通り自分の陥った罠をリストアップしたので、誰かの役にたてば幸いです

なぜかすべてのテストが通ってないので問題は残ってるけど、TravisCIの問題は解決したということで。

最終的な設定ファイル(不要な設定もあるかもしれないけど)

.travis.yml
language: go
go:
  - 1.12.x

go_import_path: github.com/YukiMiyatake/GOSICK

env:
  global:
    - GO111MODULE=on
    - DOCKER_COMPOSE_VERSION=1.24.1

services:
  - docker

before_install:
  - sudo /etc/init.d/mysql stop
  - docker-compose -v
  - docker -v
  - sudo rm /usr/local/bin/docker-compose
  - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
  - chmod +x docker-compose
  - sudo mv docker-compose /usr/local/bin
  - docker-compose build

install:

before_script:

script:
  - scripts/docker_app_test

after_script:

notifications:

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