an odd fellow

仕事のメモ

drone.ioでdocker run -vしてハマった

背景

drone.ioでreviewdogを使いたくてこんな感じで書いた。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

.drone.yml

pipeline:
  reviewdog:
    image: drone-build:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .
      - docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 . | reviewdog -ci=droneio -f=pep8"
    when:
      event: pull_request

だが、reviewdogがreviewをしてくれない。(flake8が文句を言うコードはリポジトリに含まれている)

docker run -v $PWD:$WORK_DIR reviewdog:latest /bin/bash -c "flake8 ."

としてもflake8も何も出力してくれなかった。

仮設

docker run -v $PWD:$WORK_DIR reviewdog:latest ls

としたが、droneのログに出力されなかったので、docker run -vが何らかの理由で効いておらずマウントされていないのでないかと考えた。

結論

https://stackoverflow.com/questions/31381322/docker-in-docker-cannot-mount-volume

A Docker container in a Docker container uses the parent HOST's Docker daemon and hence, any volumes that are mounted in the "docker-in-docker" case is still referenced from the HOST, and not from the Container.

Dockerコンテナの中で動かすDockerデーモンはHOSTのものらしい。なので、docker run -v で渡すファイルパスはHOSTのものになってしまっているとのこと。

なので、droneではdocker in dockerは使わないで予めDockerfile.reviewdogの中でCOPYをしてから、prepareでdocker buildするようにしました。

Dockerfile.reviewdog

FROM python:3.6

USER root
ENV HOME /root
ARG WORK_DIR
WORKDIR ${WORK_DIR}
ENV APP_ROOT ${WORK_DIR}

# install Golang
ARG GO_VERSION=1.8.3
RUN mkdir /tmp/go && \
    cd /tmp/go && \
    curl -O -sS -L https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz && \
    tar zxf go${GO_VERSION}.linux-amd64.tar.gz && \
    mkdir /usr/local/go && \
    mv go/* /usr/local/go && \
    rm -rf /tmp/go
ENV GOPATH=$HOME/go
ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

# install reviewdog
RUN go get github.com/haya14busa/reviewdog/cmd/reviewdog
ENV GITHUB_API="https://github.com/api/v3/"
ARG GITHUB_API_TOKEN=""
# build時にGITHUB_API_TOKENを渡す
ENV REVIEWDOG_GITHUB_API_TOKEN=$GITHUB_API_TOKEN

# install flake8
RUN pip install flake8 flake8-import-order flake8-double-quotes flake8-print pep8_naming

COPY . $APP_ROOT  # ここを追加

.drone.yml

pipeline:
  prepare:  #prepareでdocker buildをしてしまう
    image: drone-build:lates
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WORK_DIR=/usr/src/app
    commands:
      - export GITHUB_API_TOKEN="GITHUB_API_TOKEN"
      - docker build --build-arg WORK_DIR=$WORK_DIR --build-arg GITHUB_API_TOKEN=$GITHUB_API_TOKEN -t reviewdog:latest -f Dockerfile.reviewdog .

  reviewdog:
    image: reviewdog:latest
    environment:
      - flake8 . | reviewdog -ci=droneio -f=pep8
    when:
      event: pull_request