LoginSignup
19
10

More than 5 years have passed since last update.

CircleCI Local で setup_remote_docker を使えるようにする

Posted at

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分で強制的に切れるようです)

circleci/config.yml
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 に仕掛ければ良いことになります。

19
10
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
19
10