Hi, I am following the example on https://docs.docker.com/compose/startup-order/ to make sure the database is running before I start the application.
My Dockerfile
contains the command
CMD ["/usr/bin/java", "-jar", "/usr/lib/gumtree/api-server/server/api-server.war"]
and in my docker-compose.yml
I have
entrypoint: ["/usr/bin/wait-for-it.sh", "postgres001:5432", "-t", "120", "--"]
but after the postgres database starts the service container just exits straight away.
api_1 | wait-for-it.sh: postgres001:5432 is available after 42 seconds
postgres001_1 | LOG: database system is ready to accept connections
api_api_1 exited with code 0
Looking inside the running container I can see the entrypoint does not have the command appended
docker exec b456a362e587 ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.2 0.0 21816 3200 ? Ss 22:12 0:00 bash /usr/bin/wait-for-it.sh postgres001:5432 -t 120 --
If both command and entrypoint are in the same place (either in the Dockerfile
or in the docker-compose.yml
) the application starts up properly.
› docker exec 6cafdb9fdcf2 ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.2 0.0 21816 3208 ? Ss 22:10 0:00 bash /usr/bin/wait-for-it.sh postgres001:5432 -t 120 -- java -jar /usr/lib/gumtree/api-server/server/api-server.war
Any idea is this is a bug or I am doing something wrong?
Thanks
hmm, it does kind of feel like a bit in this case, but I think it's been this way for a while. The output of docker inspect <container name>
would be good to verify exactly what the engine is receiving.
Indeed @dnephin, the CMD gets wiped out
› docker inspect 172ab44fb462
...
"Cmd": null,
"Image": "api-server",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/usr/bin/wait-for-it.sh",
"postgres001:5432",
"-t",
"120",
"--"
]
Same here.
the same, had to put CMD in compose yaml for now...
Same here on Docker beta for OSX:
Adding the CMD in docker-compose (or re-specifying it after -- on wait-for-it) works, but it is not such a good solution considering it tightly couples the docker-file with the underlying image.
I also encounter this issue as I describe in "How can I make my Docker compose “wait-for-it” script invoke the original container ENTRYPOINT or CMD command?" and demonstrate using example docker-compose-wait-for-file
.
derek@derek-lubuntu:~/Projects/docker-compose-wait-for-file$ docker-compose up
Creating dockercomposewaitforfile_create_1
Creating dockercomposewaitforfile_wait_1
Attaching to dockercomposewaitforfile_create_1, dockercomposewaitforfile_wait_1
create_1 | Sleeping for 10 s.
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
create_1 | Created file /wait/done.
dockercomposewaitforfile_create_1 exited with code 0
wait_1 | Found file [/wait/done].
dockercomposewaitforfile_wait_1 exited with code 0
Adding a CMD
to image ubuntu-wait-for-file
doesn't help:
derek@derek-lubuntu:~/Projects/docker-compose-wait-for-file$ git diff
diff --git a/ubuntu-wait-for-file/Dockerfile b/ubuntu-wait-for-file/Dockerfile
index 20e92c0..ccbabb7 100644
--- a/ubuntu-wait-for-file/Dockerfile
+++ b/ubuntu-wait-for-file/Dockerfile
@@ -1,3 +1,4 @@
FROM ubuntu
ADD wait-for-file.sh /
RUN chmod +x /wait-for-file.sh
+CMD ["echo", "'Can you see me?'"]
derek@derek-lubuntu:~/Projects/docker-compose-wait-for-file$ docker-compose build
Building create
Step 1 : FROM ubuntu
---> b549a9959a66
Step 2 : ADD create-file.sh /
---> Using cache
---> 67e5db59f8e2
Step 3 : RUN chmod +x /create-file.sh
---> Using cache
---> c7e361b4408e
Step 4 : ENTRYPOINT /create-file.sh
---> Using cache
---> 0360027060ca
Successfully built 0360027060ca
Building wait
Step 1 : FROM ubuntu
---> b549a9959a66
Step 2 : ADD wait-for-file.sh /
---> Using cache
---> db75cb689f0e
Step 3 : RUN chmod +x /wait-for-file.sh
---> Using cache
---> d9a991cdd174
Step 4 : CMD echo 'Can you see me?'
---> Using cache
---> 19f4ad2a167c
Successfully built 19f4ad2a167c
derek@derek-lubuntu:~/Projects/docker-compose-wait-for-file$ docker-compose up
Creating dockercomposewaitforfile_create_1
Creating dockercomposewaitforfile_wait_1
Attaching to dockercomposewaitforfile_create_1, dockercomposewaitforfile_wait_1
create_1 | Sleeping for 10 s.
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
wait_1 | Waiting for file [/wait/done].
create_1 | Created file /wait/done.
dockercomposewaitforfile_create_1 exited with code 0
wait_1 | Found file [/wait/done].
dockercomposewaitforfile_wait_1 exited with code 0
Same, why docker guys not to fix it?
I am having the same issue.
entrypoint in docker-compose is wiping out CMD specified inside the dockerfile.
Here is the inspect output of the container
"Cmd": null,
"Image": "ransingh/siglee-api:61e2686",
"Volumes": {
"/home/siglee/siglee-api/log": {}
},
"WorkingDir": "/home/siglee/siglee-api",
"Entrypoint": [
"./wait_for_db",
"db"
],
Same here. :(
CMD defined in the app Dockerfile like so:
CMD ["java", "-jar", "./target/app.jar"]
Entrypoint defined in docker-compose.yml like so:
entrypoint: ["/usr/scripts/wait-for-it.sh", "db:5432", "-- "]
Container inspect on the app:
"Entrypoint": [
"/usr/scripts/wait-for-it.sh",
"cotillion_db:5432"
],
Would love to see this fixed so I don't have to copy the CMD from the container into compose (especially as a general practice for many such container + db setups).
Same for me on OSX:
docker: Docker version 1.12.0-rc4, build e4a0dbc, experimental
docker-compose: docker-compose version 1.8.0-rc2, build c72c966
It would be very nice to see this fixed.
I'm not convinced this is a bug. It's consistent with docker run
:
FROM alpine
CMD ["echo", "default command"]
$ docker build -t 3140 .
$ docker run --name no-entrypoint 3140
default command
$ docker inspect no-entrypoint
...
"Cmd": [
"echo",
"default command"
],
...
$ docker run --name with-entrypoint --entrypoint echo 3140
<outputs a blank line>
$ docker inspect with-entrypoint
...
"Cmd": null,
...
Apparently, this also happens when you set ENTRYPOINT
in a Dockerfile which inherits a CMD
from its parent image: see https://github.com/docker/docker/issues/19611.
The discussion in that issue suggests two things:
On top of that, our startup order document is wrong, as @mericano1 has discovered. So I think this is a docs issue.
If it's by design, then I think it might be useful for a container to have a straightforward mechanism to invoke the ENTRYPOINT
or CMD
of its parent, similar to how many object-oriented programming languages enable a constructor to invoke a parent constructor creating a chain of constructor invocations to the root object.
Just an addition about the docker-compose documentation. The docker-compose.yml in the example implies that the command is not deleted, if the entrypoint is set in a compose file. Maybe the example is wrong, but that was the way I ran into this trap.
Yes, that's what I mean. We should fix that, add a note to the entrypoint
documentation in the Compose file doc, and also ensure it's noted in the Engine docs for the ENTRYPOINT
Dockerfile instruction and --entrypoint
flag.
@derekmahar That's an interesting idea, but that discussion should probably happen in a new issue on docker/docker.
Same bug
Docker version 1.11.2, build b9f10c9
docker-compose version 1.8.0-rc2, build c72c966
@MrShoco It's not a bug - please read the discussion.
Compose-side docs updated in https://github.com/docker/compose/pull/3764.
Engine-side docs updated in https://github.com/docker/docker/pull/25012.
@aanand Thanks, a bug in the documentation misled me.
I face a similar problem when I have something like that on the docker-compose file:
entrypoint: /srv/wait-for-it.sh postgres:5432 --
command: bash -c "python manage.py migrate && uwsgi --ini /etc/web/uwsgi.ini --py-autoreload 1"
Also, when I try to run:
docker-compose run web bash -c "python manage.py migrate && uwsgi --ini /etc/web/uwsgi.ini --py-autoreload 1"
I get a python console only.
What am doing wrong?
I'm facing this issue too:
i have the entrypoint in docker-compose.yml:
entrypoint: ./wait-for-it.sh -t 60 --strict mydb:3306
and the cmd in the Dockerfile:
CMD ["java","-jar","Testone_10006.jar"]
It waits until the db is available but then it doesn't do anything.
same problem here
Hey, from the discussion above I understand that entrypoint
in docker-compose.yml will override CMD
in Dockerfile.
But is there a way to embed the original CMD
in Dockerfile to entrypoint
in docker-compose.yml?
Why override CMD when someone is only overriding entrypoint? Maybe, this "feature" just complicates things. Maybe it is a bug.
I'm also inclined to say I don't like this behaviour.
It would be preferable to either
a) maintain the original CMD in the parent image, such that when the child image specifies ENTYPOINT the 2 are concatenated (as expected) so you get ENTRYPOINT + CMD.
b) allow the child image to invoke the parent CMD such that you can manually compose ENTRYPOINT + CMD without having to copy/paste CMD from the parent image into your child dockerfile.
Otherwise; there is no way for child images to prefix a cmd in a parent image without having to duplicate the parent CMD invocation. The parent CMD might change in a subsequent version of the parent image, consequently causing the child image to break because the copied invocation is incorrect now.
This is really confusing to me. It seems crucial for a compose file to _prepend_ to the command that's run by the underlying Dockerfile
.
The compose file should _not_, IMO, be in charge of the commands run by the underlying Dockerfile
unless that's the author's intention. This means that every time my Dockerfile
commands change, for the multitude of application images I'm using, I have to know to also update my compose file - effectively duplicating config.
There needs to be a way to run a command (specified by the compose file) _prior_ to the execution of the underlying CMD
specified by the Dockerfile
.
Closing as this is not a Compose issue.
Is there a way to do this now?
I wish to prepend something to the command specified in the Dockerfile (in my case, a wait-for-it.sh call in order to wait for my DB service to start before the actual service starts) and have no way to call the "child" command (the one specified in the Dockerfile), having to resort to duplicating configuration, as mentioned above...
If there is no way to do this but to duplicate configuration I hereby request the issue to be reopened. Furthermore, this is clearly a compose issue, as defining the entrypoint in the docker-compose.yml file is what clears the command option - thus it cannot be anything BUT a compose issue.
I agree with @miguelpduarte's suggestion to reopen. If the maintainers (@shin-) disagree, can you please elaborate as to why this is:
not a Compose issue.
Even if the original Dockerfile command were to be exposed to the Compose file as a variable, that would allow maintainers of the "parent" Compose files to write their own entrypoints which are decoupled from the command logic/behavior of the underlying/"child" Dockerfile. As has been mentioned multiple times in this thread, wait-for-it
is a very common use case:
entrypoint: ./wait-for-it.sh -t 60 --strict mydb:3306 && sh -c $DOCKERFILE_CMD
_(I don't remember the exact wait-for-it syntax, but you get the idea.)_
Thanks
Please refer to earlier responses in this thread: https://github.com/docker/compose/issues/3140#issuecomment-234267729
This is the engine's behavior. We can't do anything about it from Compose's end. If you want to suggest it be changed, you'll need to submit a proposal on the moby/moby repo.
@shin- Is it not possible for Compose to offer, even as a secondary option, the ability to _prepend_ the Docker container's command with the entrypoint command defined in the Compose file? As described: https://github.com/docker/compose/issues/3140#issuecomment-271095004
It seems if it has the ability to overwrite it, it should also have the ability to add to it, and that's what I think most of the folks in this thread are focused on accomplishing.
Finally,
I just made another shell script to execute
each command
for docker-compose
#!/bin/sh
sudo docker-compose -f docker-compose.myfile.yml pull && sudo docker-compose -f docker-compose.myfile.yml up -d && docker exec $container /myfile.sh
Any updates? This overriding behavior is really annoying.
The above proposed syntax to call CMD from Dockerfile was good.
entrypoint: ./wait-for-it.sh -t 60 --strict mydb:3306 && sh -c $DOCKERFILE_CMD
Because of this issue docker-compose is essentially worthless for anything but dev work. You certainly can't prototype out prod deploys with it.
Perhaps terraform is the better solution.
Did anyone start an issue in the engine repo after all?
Christ, this is so annoying. Facing the same issue here.
Most helpful comment
This is really confusing to me. It seems crucial for a compose file to _prepend_ to the command that's run by the underlying
Dockerfile
.The compose file should _not_, IMO, be in charge of the commands run by the underlying
Dockerfile
unless that's the author's intention. This means that every time myDockerfile
commands change, for the multitude of application images I'm using, I have to know to also update my compose file - effectively duplicating config.There needs to be a way to run a command (specified by the compose file) _prior_ to the execution of the underlying
CMD
specified by theDockerfile
.