CircleCI 2.0 は docker ネイティブなので、setup_remote_docker をすることで docker を使ったテストやビルド等の様々なジョブが実行できます。
しかしながら、例えば docker volume create
をやっている場合は、CLI だとそのままでは以下のようなエラーが出てしまいます。
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.38/volumes/create: dial unix /var/run/docker.sock: connect: permission denied
いろいろと不便なので、なんとかしてみた結果がこちら。
結論
config.yml の steps の序盤で以下の処理を実行すれば解決。
if [[ $CIRCLE_SHELL_ENV =~ "localbuild" ]]; then
sudo chown root /usr/bin/docker
sudo chmod u+s /usr/bin/docker
fi
調査内容メモ
とりあえず setup_remote_docker した後、sleep をかますだけの config を用意。(10分で強制的に切れるようです)
version: 2
jobs:
build:
working_directory: ~/app
docker:
- image: circleci/python:3.6
steps:
- setup_remote_docker
- run:
name: test
command: sleep 600
circleci local execute
で実行。
% circleci local execute
Docker image digest: sha256:525c91e01875050fbf65cdb4bc83a45744c54f9027fa05f76f88713f3d37f4e3
====>> Spin up Environment
Build-agent version 0.0.7725-9681bc36 (2018-08-09T15:10:50+0000)
Starting container circleci/python:3.6
using image circleci/python@sha256:3d2fcd53ad4b75c4e7cdeb0bbf18264ffa708c4a9216dbbe419df786c9c8310e
Using build environment variables:
BASH_ENV=/tmp/.bash_env-localbuild-1536222453
CI=true
CIRCLECI=true
CIRCLE_BRANCH=xxxxxxxx
CIRCLE_BUILD_NUM=
CIRCLE_JOB=build
CIRCLE_NODE_INDEX=0
CIRCLE_NODE_TOTAL=1
CIRCLE_REPOSITORY_URL=git@github.com:xxxxxxxx.git
CIRCLE_SHA1=2760e26695363d6497c2c236709a705db92d0009
CIRCLE_SHELL_ENV=/tmp/.bash_env-localbuild-1536222453
CIRCLE_WORKING_DIRECTORY=~/app
====>> Setup a remote Docker engine
Using local docker engine bind-mounted
====>> test
#!/bin/bash -eo pipefail
sleep 600
Using local docker engine bind-mounted と言ってます。
sleep したところで、別ターミナルで docker ps
してみると、circleci/picard(CLI 本体)と circleci/python:3.6(メインコンテナ)が動いてます。
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e1ebbeccc823 circleci/python:3.6 "/bin/sh" 7 seconds ago Up 5 seconds vigorous_brattain
16ba46868114 circleci/picard "circleci build" 9 seconds ago Up 7 seconds hardcore_murdock
docker inspect
してみると、circleci コマンドが動かすコンテナはどうやら /var/run/docker.sock を /var/run/docker-temp.sock としてマウントしており、docker コマンドが入っているイメージ(circleci/python:3.6 等)を使えばそのまま接続できそうです。
% docker inspect vigorous_brattain
...snip...
"Mounts": [
{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Destination": "/var/run/docker-temp.sock",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
...snip...
docker exec
で覗いてみます。
% docker exec -it vigorous_brattain bash
circleci@e1ebbeccc823:/$ ls -al /var/run
lrwxrwxrwx 1 root root 4 Aug 31 00:00 /var/run -> /run
circleci@e1ebbeccc823:/$ ls -al /run
total 16
drwxr-xr-x 1 root root 4096 Sep 6 08:33 .
drwxr-xr-x 1 root root 4096 Sep 6 08:33 ..
srw-rw---- 1 root root 0 Sep 5 02:54 docker-temp.sock
lrwxrwxrwx 1 root root 25 Sep 6 08:33 docker.sock -> /var/run/docker-temp.sock
drwxr-x--- 2 Debian-exim Debian-exim 4096 Sep 6 00:06 exim4
drwxrwxrwt 2 root root 4096 Aug 31 00:00 lock
-rw-rw-r-- 1 root utmp 0 Aug 31 00:00 utmp
/var/run
は /run
への symlink、さらに /run/docker.sock
が /var/run/docker-temp.sock
になっています。
普通に docker run
すると、件のエラーが出ます。
circleci@e1ebbeccc823:/$ docker run --rm -it busybox
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.38/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
せっかくローカルでは Docker for Mac が動いているのに permission denied とは惜しい感じですが、sudo かますと繋がります。
circleci@e1ebbeccc823:/$ sudo docker run --rm -it busybox
/ #
ただ、config.yml の docker コマンドに sudo をつけてしまうと変更箇所が多いのと、circleci.com 上で動かなくなってしまうので、コマンド自体は変更せずに setuid でやってみます。
circleci@e1ebbeccc823:/$ which docker
/usr/bin/docker
circleci@e1ebbeccc823:/$ ls -al /usr/bin/docker
-rwxr-xr-x 1 1000 1000 37589867 Aug 21 17:29 /usr/bin/docker
オーナーが root ではなく uid:1000 になっているので、chown と chmod のコンボで。
circleci@e1ebbeccc823:/$ sudo chown root /usr/bin/docker
circleci@e1ebbeccc823:/$ sudo chmod u+s /usr/bin/docker
circleci@e1ebbeccc823:/$ ls -al /usr/bin/docker
-rwsr-xr-x 1 root 1000 37589867 Aug 21 17:29 /usr/bin/docker
sudo なしで動くかどうか確認してみます。
circleci@e1ebbeccc823:/$ docker run --rm -it busybox
/ #
無事 setuid した状態で動きました。
後は、circleci.com と local の切り分けですが、circleci local execute
した際には CIRCLE_SHELL_ENV
に localbuild という文字が含まれるので、これを検知して chown/chmod するように、config.yml の序盤の step に仕掛ければ良いことになります。