Compose: "docker-compose exec" does not write to STDERR

Created on 21 Sep 2017  路  9Comments  路  Source: docker/compose

This is similar to #3267, but for exec.

When you exec something, both STDOUT and STDERR are on STDOUT.

I created an example repository to reproduce this.

My use case is quite simple:
I have a Mysql instance and want to run a database dump, piping its output to the host, e.g.

docker-compose exec mysql mysqldump -ufoo -pbar baz > /var/backups/foo.sql

Having its warning messages (from STDERR) inside the dump file is a problem.

PS: Fun fact: On Postgres, I did not stumble upon this problem, because pg_dump rocks! ;)

arecli kinenhancement

Most helpful comment

It works beautifully. Thanks!

felix@locutus /tmp $ sudo wget -q https://github.com/docker/compose/releases/download/1.19.0-rc1/docker-compose-Linux-x86_64 -O /usr/local/bin/docker-compose
felix@locutus /tmp $ sudo chmod +x /usr/local/bin/docker-compose
felix@locutus /tmp $ [[ $(which docker-compose) == /usr/local/bin/docker-compose ]] && echo OK
OK

felix@locutus /tmp $ git clone -q https://github.com/felixhummel/compose-bug-stderr.git
felix@locutus /tmp $ cd compose-bug-stderr/

felix@locutus master /tmp/compose-bug-stderr $ docker-compose build
Building app
Step 1/4 : FROM alpine:3.6
3.6: Pulling from library/alpine
605ce1bd3f31: Pull complete
Digest: sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106
Status: Downloaded newer image for alpine:3.6
 ---> 77144d8c6bdc
Step 2/4 : COPY bin/main /usr/local/bin/main
 ---> 59fb09ea7d21
Step 3/4 : COPY bin/dump /usr/local/bin/dump
 ---> b55f922132f0
Step 4/4 : CMD ["/usr/local/bin/main"]
 ---> Running in 72fcccafbee4
Removing intermediate container 72fcccafbee4
 ---> 50621f018d01
Successfully built 50621f018d01
Successfully tagged composebugstderr_app:latest

felix@locutus master /tmp/compose-bug-stderr $ docker-compose up -d
Creating network "composebugstderr_default" with the default driver
Creating composebugstderr_app_1 ... done

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump > /dev/null
Hello stderr!

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump 2> /dev/null
Hello stdout!

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump
Hello stderr!
Hello stdout!

All 9 comments

You need to use -T to disable TTY allocation.

This did not work for me. See https://github.com/felixhummel/compose-bug-stderr#the-minus-t-flag

versions:

docker-compose version 1.11.2, build dfed245
Docker version 17.06.2-ce, build cec0b72

Indeed, my bad. I'll take a look at our options here when I have some time.

Quick workaround for now can be ignoring stderr in container. So instead of

docker-compose exec mysql mysqldump -ufoo -pbar baz > /var/backups/foo.sql

you can have:

docker-compose exec mysql sh -c "mysqldump -ufoo -pbar baz 2>/dev/null" > /var/backups/foo.sql

This should work with 1.19.0 RC1 - please try it out and let me know!

It works beautifully. Thanks!

felix@locutus /tmp $ sudo wget -q https://github.com/docker/compose/releases/download/1.19.0-rc1/docker-compose-Linux-x86_64 -O /usr/local/bin/docker-compose
felix@locutus /tmp $ sudo chmod +x /usr/local/bin/docker-compose
felix@locutus /tmp $ [[ $(which docker-compose) == /usr/local/bin/docker-compose ]] && echo OK
OK

felix@locutus /tmp $ git clone -q https://github.com/felixhummel/compose-bug-stderr.git
felix@locutus /tmp $ cd compose-bug-stderr/

felix@locutus master /tmp/compose-bug-stderr $ docker-compose build
Building app
Step 1/4 : FROM alpine:3.6
3.6: Pulling from library/alpine
605ce1bd3f31: Pull complete
Digest: sha256:3d44fa76c2c83ed9296e4508b436ff583397cac0f4bad85c2b4ecc193ddb5106
Status: Downloaded newer image for alpine:3.6
 ---> 77144d8c6bdc
Step 2/4 : COPY bin/main /usr/local/bin/main
 ---> 59fb09ea7d21
Step 3/4 : COPY bin/dump /usr/local/bin/dump
 ---> b55f922132f0
Step 4/4 : CMD ["/usr/local/bin/main"]
 ---> Running in 72fcccafbee4
Removing intermediate container 72fcccafbee4
 ---> 50621f018d01
Successfully built 50621f018d01
Successfully tagged composebugstderr_app:latest

felix@locutus master /tmp/compose-bug-stderr $ docker-compose up -d
Creating network "composebugstderr_default" with the default driver
Creating composebugstderr_app_1 ... done

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump > /dev/null
Hello stderr!

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump 2> /dev/null
Hello stdout!

felix@locutus master /tmp/compose-bug-stderr $ docker exec $(docker-compose ps -q app) /usr/local/bin/dump
Hello stderr!
Hello stdout!

@felixhummel Am I missing something? Your attempt with 1.19.0 appears to use docker exec instead of docker-compose exec for the stdout/stderr test.
I'm on docker-compose 1.21.2, and still have this issue where both stdout and stderr from the container are combined.

@timwhite you're right, but at least using -T looks good:

$ docker-compose --version
docker-compose version 1.21.2, build a133471
$ docker-compose exec -T app /usr/local/bin/dump > /tmp/stdout
Hello stderr!
$ cat /tmp/stdout 
Hello stdout!

Furthermore, if you use docker exec -t, it doesn't work either.

You need to use -T to disable TTY allocation.

Looks like allocating a TTY implies not having this work properly, and it also looks like this will not be fixed, here is why: https://github.com/moby/moby/issues/19696#issuecomment-174832094

So this isn't really a docker-compose issue, unless maybe you think allocating a tty should be opt-in (right now it is opt-out).

Was this page helpful?
0 / 5 - 0 ratings