Permissions issue with compose build vs docker build

I expected that docker-compose merely invoked docker build with options as specified in the docker-compose.yml file, this trivial project builds fine using docker build but fails with a permissions issue when built using docker-compose build.

Dockerfile

$ cat Dockerfile
FROM centos:7.1.1503
COPY testprog /testprog
RUN ls -l /testprog && \
    echo "umask=$(umask)" && \
    /testprog

testprog

$ cat testprog
#!/bin/bash
echo "Hello world!"

Successful build using docker build

$ docker build --no-cache .
Sending build context to Docker daemon 9.728 kB
Step 1 : FROM centos:7.1.1503
 ---> 30e55721fefe
Step 2 : COPY testprog /testprog
 ---> 52efb40d693d
Removing intermediate container 565d52f67349
Step 3 : RUN ls -l /testprog &&     echo "umask=$(umask)" &&     /testprog
 ---> Running in 0c66e2e68d6d
-rwxr-xr-x 1 root root 33 Mar 23 15:01 /testprog
umask=0022
Hello world!
 ---> 38ccbaaec50d
Removing intermediate container 0c66e2e68d6d
Successfully built 38ccbaaec50d
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Note the permissions include execute access for all, the umask=0022, and that the script runs without issue.

The same build with docker-compose

docker-compose.yml

$ cat docker-compose.yml
version: '2'

services:
    project:
        build: .

This time note the lack of execute permission, and the subsequent failure:

$ docker-compose build
Building project
Step 1 : FROM centos:7.1.1503
 ---> 30e55721fefe
Step 2 : COPY testprog /testprog
 ---> c3fe12ca832c
Removing intermediate container f4cfaf797832
Step 3 : RUN ls -l /testprog &&     echo "umask=$(umask)" &&     /testprog
 ---> Running in b0d944c93374
-rw-rw-rw- 1 root root 33 Mar 23 15:01 /testprog
umask=0022
/bin/sh: /testprog: Permission denied
eERROR: Service 'project' failed to build: The command '/bin/sh -c ls -l /testprog &&     echo "umask=$(umask)" &&     /testprog' returned a non-zero code: 126

Why does this change depending on which tool initiates the build? I’d expect docker-compose to use docker build under the covers. Is this a bug?

I’m having the exact same problem.
Did you find a solution for this?

Unfortunately, no, I didn’t find a solution. Between poor documentation and several nagging issues like this, I quit using compose for now and have my own set of scripts for building, running and managing volumes and networks. At some point I’ll go back and give compose another try in the hopes of retiring my scripts.

Sorry, I don’t have any answers for you,

Marc

Hi Marc,

Thank you for answering my question.

A possible workaround for this issue:

  • Build the images with docker
  • Instruct compose to use the image build by docker instead of building the image.

docker-compose.yml
version: '2’
services:
project:
image: your/image

No problem. My workaround at the time was to chmod each file in the Dockerfile to ensure they got the desired permissions. That just shouldn’t be necessary under Compose if it isn’t with “docker build”. What else isn’t happening the same and why aren’t they using the same underlying technology?

The warning is not an error.
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have ‘-rwxr-xr-x’ permissions. It is recommended to double check and reset permissions for sensitive files and directories.

Set the permissions as suggested.

My question was why it behaves differently between “docker build” and “docker compose”. I expected that compose was merely a layer on top of build/run/etc driven by the yaml metadata.

Apparently, it’s not that simple.

Permissions should be set for the files and directories created automatically. Could be a bug.