Alpine: Wait for docker to start before continue

Viewed 2214

I am using Alpine linux for my CI/CD machine. The docker file below:

FROM node:10.15-alpine
RUN npm i -g sequelize sequelize-cli mysql2
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk update
RUN apk add --update git bash openssh terraform aws-cli docker openrc
WORKDIR /var/app

Problem is when the CI tries to execute docker code, eg. docker login, it fails:

[Container] 2019/01/10 11:18:10 Running command $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Warning: failed to get default registry endpoint from daemon (Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?). Using system default: https://index.docker.io/v1/
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
 [Container] 2019/01/10 11:18:10 Command did not exit successfully $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email) exit status 1

When I try to add the line

RUN service docker start

I get docker already starting

How can I wait for docker to start then?

2 Answers

Do consider @DavidMaze answer, supposedly DinD is not the correct way, but I think it seems easier ... furthermore I found docs on AWS on how to make this work.

https://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker-custom-image.html

Key points I learnt is I need to enable priviledged mode on CodeBuild, then in my buildspec, I need to do:

phases:
  install:
    commands:
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&
      - timeout -t 15 sh -c "until docker info; do echo .; sleep 1; done"

Nothing you show actually starts a Docker daemon (beyond the one running on the host).

Trying to launch Docker in Docker is a complex and generally disrecommended setup. A long-time Docker dev specifically recommends not using it for CI; there is a precanned docker image where the very first sentence of the official image description begins

Although running Docker inside Docker is generally not recommended....

The Dockerfile you show doesn't include an ENTRYPOINT or CMD directive. That means it will inherit it from node, which has a default CMD of just running node. In short: when you run this image, unless you specify something else at the command line, it will launch an interactive Node.js shell, and not any of the unrelated tools you've bundled into the same image. Specifically, it will not start a Docker daemon.

Putting RUN service ... start into your Dockerfile doesn't help you for a couple of reasons. One is that Docker images only contain filesystem content and not running processes, so after that RUN step finishes, nothing is running any more. Some init systems (especially systemd) depend on communicating with the init process, which also won't be running, so especially systemctl in Docker almost never works. Architecturally it's usually better to run one process in a container (so docker stop will stop the process you care about, and so that Docker will notice if the process crashes, and for scaling, and ...) so you should almost never use service, initctl, or systemctl in Docker.

The general advice for CI tools is to bind-mount the host's Docker socket (docker run -v /var/run/docker.sock:/var/run/docker.sock) and let it build images and start containers on its own, accepting the security implications.

Related