Search code examples
linuxubuntudockerdockerfiletar

Dockerfile ADD tar.gz does not extract on ubuntu VM with Docker


I have a Docker Image which I want to build and when I run the build command on my Windows and Mac Docker it works fine and builds correctly, but if I run the same Dockerfile-Build on a Ubuntu-Server VM with docker I get an error.

The critical part of my Dockerfile is:

[...]
# Dependencies
RUN apt-get update && apt-get install -y apt-utils curl git tar gzip
# Install Go
ENV GO_VERSION 1.8
WORKDIR /tmp
ADD https://storage.googleapis.com/golang/go$GO_VERSION.linux-amd64.tar.gz ./
RUN mv go /usr/local/
[...]

But on the Ubuntu-server VM is fails at the RUN mv go /usr/local/-step

And producing the following error:

Step 10/24 : RUN mv go /usr/local/
 ---> Running in 6b79a20769eb
mv: cannot stat ‘go’: No such file or directory

And I suppose it does not extract the downloaded tar.gz correctly (but the download works)

Do you guys have any idea?


Solution

  • This is a known issue with 17.06 and patched in 17.06.1. The documented behavior is to download the tgz but not unpack it when pulling from a remote URL. Automatically unpacking the tgz was an unexpected change in behavior in 17.06 that they reverted back to only downloading the tgz in 17.06.1.

    Release notes for 17.06 (see the note at the top): https://github.com/docker/docker-ce/releases/tag/v17.06.0-ce

    Release notes for 17.06.01: https://github.com/docker/docker-ce/releases/tag/v17.06.1-ce

    Issue: https://github.com/moby/moby/issues/33849

    PR of Fix: https://github.com/docker/docker-ce/pull/89


    Edit, the minimize the number of layers in your image, I'd recommend doing the download, unpack, and cleanup as a single RUN command in your Dockerfile. E.g. here are two different Dockerfiles:

    $ cat df.tgz-add
    FROM busybox:latest
    ENV GO_VERSION 1.8
    WORKDIR /tmp
    
    ADD https://storage.googleapis.com/golang/go$GO_VERSION.linux-amd64.tar.gz ./
    RUN tar -xzf go$GO_VERSION.linux-amd64.tar.gz \
     && rm go$GO_VERSION.linux-amd64.tar.gz
    
    CMD ls -l .
    
    $ cat df.tgz-curl
    FROM busybox:latest
    ENV GO_VERSION 1.8
    WORKDIR /tmp
    
    RUN wget -O go$GO_VERSION.linux-amd64.tar.gz https://storage.googleapis.com/golang/go$GO_VERSION.linux-amd64.tar.gz \
     && tar -xzf go$GO_VERSION.linux-amd64.tar.gz \
     && rm go$GO_VERSION.linux-amd64.tar.gz
    
    CMD ls -l .
    

    The build output is truncated here...

    $ docker build -t test-tgz-add -f df.tgz-add .
    ...
    
    $ docker build -t test-tgz-curl -f df.tgz-curl .
    ...
    

    They run identically:

    $ docker run -it --rm test-tgz-add
    total 4
    drwxr-xr-x   11 root     root          4096 Aug 31 20:27 go
    
    $ docker run -it --rm test-tgz-curl
    total 4
    drwxr-xr-x   11 root     root          4096 Aug 31 20:29 go
    

    However, doing a single RUN to download, build, and cleanup saves you the 80MB of download from your layer history:

    $ docker images | grep test-tgz
    test-tgz-curl               latest                                     2776133659af        30 seconds ago      269MB
    test-tgz-add                latest                                     d625455998ff        2 minutes ago       359MB