moby: WORKDIR causes docker build to not use cache

Description

WORKDIR in a Dockerfile causes docker build -t t . to not cache layers.

Steps to reproduce the issue:

  1. Use the following Dockerfile
FROM alpine

WORKDIR /opt/whatever

RUN sleep 5s

CMD ["echo", "stuff"]
  1. run docker build -t t .
  2. run docker build -t t . again. Observe that there was no caching used.

Describe the results you received:

The results of two consecutive builds results in no caching in the second build:

 λ docker build -t t .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM alpine
 ---> 88e169ea8f46
Step 2/4 : WORKDIR /opt/whatever
 ---> ab24c914f7ad
Removing intermediate container f5e5d62d8476
Step 3/4 : RUN sleep 5s
 ---> Running in 5f63d943d5f1
 ---> cdf23a3419c7
Removing intermediate container 5f63d943d5f1
Step 4/4 : CMD echo stuff
 ---> Running in 938cad195763
 ---> 71e2b1215dc4
Removing intermediate container 938cad195763
Successfully built 71e2b1215dc4
 λ docker build -t t .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM alpine
 ---> 88e169ea8f46
Step 2/4 : WORKDIR /opt/whatever
 ---> 608d9e2b6d66
Removing intermediate container 85b77e27cd63
Step 3/4 : RUN sleep 5s
 ---> Running in 5109be334f42
 ---> bfbd8ab7ca7d
Removing intermediate container 5109be334f42
Step 4/4 : CMD echo stuff
 ---> Running in 86c5dbb64f66
 ---> 508ed4147f5b
Removing intermediate container 86c5dbb64f66
Successfully built 508ed4147f5b

Describe the results you expected:

All layers should be cached when building the second time.

Additional information you deem important (e.g. issue happens only occasionally):

Issue seems to be related to WORKDIR

Output of docker version:

Client:
 Version:      1.13.0-rc5
 API version:  1.25
 Go version:   go1.7.3
 Git commit:   43cc971
 Built:        Thu Jan  5 03:07:30 2017
 OS/Arch:      darwin/amd64

Server:
 Version:      1.13.0-rc5
 API version:  1.25 (minimum version 1.12)
 Go version:   go1.7.3
 Git commit:   43cc971
 Built:        Thu Jan  5 03:07:30 2017
 OS/Arch:      linux/amd64
 Experimental: true

Output of docker info:

Containers: 11
 Running: 0
 Paused: 0
 Stopped: 11
Images: 61
Server Version: 1.13.0-rc5
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins: 
 Volume: local
 Network: bridge host ipvlan macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 03e5862ec0d8d3b3f750e19fca3ee367e13c090e
runc version: 51371867a01c467f08af739783b8beafc154c4d7
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.8.15-moby
Operating System: Alpine Linux v3.5
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 1.952 GiB
Name: moby
ID: A3C4:SQBJ:CPK5:UGNZ:6CKX:WFZ2:SRNA:JDFV:HC3Y:A2GP:S5RY:TJ5B
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: 17
 Goroutines: 29
 System Time: 2017-01-12T00:03:28.636038728Z
 EventsListeners: 1
Registry: https://index.docker.io/v1/
Experimental: true
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Additional environment details (AWS, VirtualBox, physical, etc.):

Docker for Mac Version 1.13.0-rc5-beta35 (14875) Channel: Beta 25211e84dd

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 20 (8 by maintainers)

Most upvoted comments

Current versions of docker-compose and docker build in many (or all) cases will not share the build cache, or at least not produce the same digest. The reason for that is that when sending the build context with docker-compose, it will use a slightly different compression (docker-compose is written in Python, whereas the docker cli is written in Go). There may be other differences due to them being a different implementation (and language).

The next release of docker compose will have an (currently opt-in) feature to make it use the actual docker cli to perform the build (by setting a COMPOSE_DOCKER_CLI_BUILD=1 environment variable). This was implemented in https://github.com/docker/compose/pull/6865

With that feature, docker compose can also use BuildKit for building images (setting the DOCKER_BUILDKIT=1 environment variable). I would highly recommend using buildkit for your builds if possible. When using BuildKit (requires Docker 18.09 or up, and at this point is not supported for building Windows containers), you will see a huge improvement in build-speed, and the duration taken to send the build-context to the daemon in repeated builds (buildkit uses an interactive session to send only those files that are needed during build, instead of uploading the entire build context).

As @FernandoMiguel mentioned; Docker 17.09 is indeed very old, and should not be used as it reached EOL a long time ago, is no longer maintained, and has known, unpatched vulnerabilities, some of which are critical.

Quite likely, the WORKDIR issue may also be resolved in newer versions of Docker.

@FernandoMiguel did you add your Dockerfile to .dockerignore ? Otherwise it’s probably because the Dockerfile was modified, so the cache for . being invalidated

Yup, this is fixed in 1.13.0-rc6, which is available now

Thanks for reporting @ChristopherBiscardi! I’ll close this one, but ping me if you’re still seeing this on rc6

My workaround:

RUN mkdir -p /app
WORKDIR /app
RUN echo TEST CACHE

I guess it might be cache-busting when the directory does not exist?

image It looks like I’m having something similar to the original issue. The first output is from CircleCI running docker 17.09.0-ce from docker-compose. The second output is from CircleCI running docker 17.09.0-ce from docker build command. And the third one is from my local setup with docker 19.03.3-ce where I’m trying to reproduce it with docker build command.