Jakub Koralewski
Jakub Koralewski

Reputation: 693

Docker isn't caching Alpine apk add command

Everytime I build the container I have to wait for apk add docker to finish which takes a long time. Since everytime it downloads the same thing, can I somehow force Docker to cache apk's downloads for development purposes?

Here's my Dockerfile:

FROM golang:1.13.5-alpine

WORKDIR /go/src/app
COPY src .

RUN go get -d -v ./...
RUN go install -v ./...

RUN apk add --update docker

CMD ["app"]

BTW, I am using this part volumes: - /var/run/docker.sock:/var/run/docker.sock in my docker-compose.yml to use sibling containers, if that matters.

EDIT: I've found google to copy docker.tgz in Chromium:

# add docker client -- do not install docker via apk -- it will try to install
# docker engine which takes a lot of space as well (we don't need it, we need
# only the small client to communicate with the host's docker server)
ADD build/docker/docker.tgz /

What is that docker.tgz? How can I get it?

Upvotes: 7

Views: 6500

Answers (3)

Nitin
Nitin

Reputation: 11186

You can download Docker x86_64 binaries for mac, linux, windows and unzip/untar and make it executable.

Whenever you are installing any packages in Docker container those should go at the beginning of Dockerfile, so it won’t ask you again to install same packages and COPY command part must be at the end of Dockerfile.

Upvotes: 1

Adiii
Adiii

Reputation: 59966

Reorder your Dockerfile and it should work.

FROM golang:1.13.5-alpine
RUN apk add --update docker

WORKDIR /go/src/app
COPY src .
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["app"]

As you are copying before installation, so whenever you change something in src the cache will invalidate for docker installtion.

Upvotes: 14

David Maze
David Maze

Reputation: 158995

Whenever you have a COPY command, if any of the files involve change, it causes every command after that to get re-run. If you move your RUN apk add ... command to the start of the file before it COPYs anything, it will get cached across runs.

A fairly generic recipe for most Dockerfiles to accommodate this pattern looks like:

FROM some-base-image

# Install OS-level dependencies
RUN apk add or apt-get install ...

WORKDIR /app

# Install language-level dependencies
COPY requirements.txt requirements.lock ./
RUN something install -r requirements.txt

# Install the rest of the application
COPY main.app ./
COPY src src/

# Set up standard run-time metadata
EXPOSE 12345
CMD ["/app/main.app"]

(Go and Java applications need the additional step of compiling the application, which often lends itself to a multi-stage build, but this same pattern can be repeated in both stages.)

Upvotes: 2

Related Questions