How to append command to docker-compose.yml without override existing? - docker

In docker-compose.yml I have a service
app:
image: yiisoftware/yii2-php:7.1-apache
volumes:
- ~/.composer-docker/cache:/root/.composer/cache:delegated
- ./:/app:delegated
ports:
- '80:80'
depends_on:
- db
So I want to execute command yii migrate --interactive=0 when container is started. But if I just add string
command: "yii migrate --interactive=0"
It override command that already specified in yiisoftware/yii2-php:7.1-apache dockerfile. How can I append command, not replace? Is it possible?
I already googled for this problem, but most popular solution is "create your own dockerfile". Can I solve this without create/modify dockerfile or shell script, only with docker-compose?

To do this, you would have to define your own ENTRYPOINT in your docker-compose.yml. Besides building your own Dockerfile, there is no way around this.
As much as I am searching, I cannot find a CMD instruction in this image's Dockerfile, though. So this is probably what's being used.
I'm not familiar with PHP, so I cannot estimate what you would have to change to run a container with your specific needs, but these are the points that you should have a look at.

You can include the pre-existing command in your new command. Now understand that everything in those commands can be called from sh or bash. So look up the existing command by doing an:
docker image inspect yiisoftware/yii2-php:7.1-apache
Then check the command in Config { Command }. (Not ConatinerConfig.) So if the existing command had been:
"start-daemon -z foo-bar"
then your new command would be:
sh -c "start-daemon -z foo-bar; yii migrate --interactive=0"
Now you'll have the existing command plus your new command and the desired effect.

Related

docker-compose collapse after running another instance of docker-compose [duplicate]

My situation. Trying to run a docker-compose structure several times on the same box. This is my docker-compose.yml:
version: '3'
services:
code:
image: organization:java-maven
links:
- mysql:mysql
volumes:
- "${PWD}:/home/ubuntu/src"
mysql:
image: organization:mysql
Running this twice with docker-compose run code mvn clean test creates two containers of code and one container of mysql.
Now, I want one code to be linked to one mysql, and another code linked to another mysql.
How do I accomplish this? This is supposed to run on jenkins slaves and the maven executions cannot share mysql.
I've miserably failed trying with the "-e KEY=VALUE" option for docker-compose run together with container_namein the docker compose file.
Not sure how to approach this, please help, thank you.
So, I focused too much on using directives to alter container names manually. The solution was much easier.
docker-compose -p anything run code mvn clean test
docker-compose -p anything_else run code mvn clean test
So, this is the project name solution. Docker compose will use the value given with the option -p as a prefix when creating container names. That means no collision.
Very handy!
For more reading: documentation around project-name option

How do I keep a copy of the options I use to run an image in Docker?

I just figured out how to get swagger-ui up and running with Docker with my own openapi.json file using the following command:
docker run -p 80:8080 -e SWAGGER_JSON=/foo/openapi.json -v ~/source:/foo swaggerapi/swagger-ui
The openapi.json file is in source control and this could be run in lots of places.
Is there any way to make this command easy to rerun other than just putting it in a README? Can I use a Dockerfile for this? Or could I use docker-compose? The most important part is just to make it easy, and then later to make it easy to change/add options.
I also know I could use a bash script that I could just change, but I'm wondering if there's any Docker way to do it, and not a hack.
docker-compose is your perfect solution:
//docker-compose.yml
version: '3.7'
services:
swagger:
image: swaggerapi/swagger-ui
ports:
- "80:8080"
environment:
- SWAGGER_JSON=/foo/openapi.json
volumes:
- "~/source:/foo "
to run it, just hit docker-compose up and you are all set
I prefer using docker-compose for more complicated runs to keep all options in yaml file. Then all you need to start container is docker-compose up.
For more options inside application you can use .env file.
I think it’s the clearest way to make containers running and doesn’t require any knowledge for the next users/developers of this environment .

Can't overwrite file in docker compose

I'm using docker compose to set up a payara server and need to overwrite the domain.xml file. I'm currently doing it through
volumes:
- './domain.xml:/opt/payara41/glassfish/domains/domain1/config/domain.xml'
but when i compose it with docker-compose up it keeps saying that it could not rename domain.xml to domain.xml.bak. Is there any way i can get permissions to overwrite it or make sure the rename works ?
Something like this should work:
command: sh -c 'cp /tmp/domain.xml /opt/payara41/glassfish/domains/domain1/config/domain.xml && YOUR_PREVIOUS_COMMAND'
volumes:
- ./domain.xml:/tmp/domain.xml
Or edit your current command (or CMD) if it's a script, prepending the copy.
Edit: This alternative is very handy and elegant.
command: sh /run-from-compose.sh
volumes:
- ./domain.xml:/tmp/domain.xml
- ./run-from-compose.sh:/run-from-compose.sh
run-from-compose.sh:
#!/bin/sh
cp /tmp/domain.xml /opt/payara41/glassfish/domains/domain1/config/domain.xml
YOUR_PREVIOUS_COMMAND
You don't need to modify the image, just mount a custom script that acts as command.

How do I run the same docker-compose.yml several times on same docker daemon with different names?

My situation. Trying to run a docker-compose structure several times on the same box. This is my docker-compose.yml:
version: '3'
services:
code:
image: organization:java-maven
links:
- mysql:mysql
volumes:
- "${PWD}:/home/ubuntu/src"
mysql:
image: organization:mysql
Running this twice with docker-compose run code mvn clean test creates two containers of code and one container of mysql.
Now, I want one code to be linked to one mysql, and another code linked to another mysql.
How do I accomplish this? This is supposed to run on jenkins slaves and the maven executions cannot share mysql.
I've miserably failed trying with the "-e KEY=VALUE" option for docker-compose run together with container_namein the docker compose file.
Not sure how to approach this, please help, thank you.
So, I focused too much on using directives to alter container names manually. The solution was much easier.
docker-compose -p anything run code mvn clean test
docker-compose -p anything_else run code mvn clean test
So, this is the project name solution. Docker compose will use the value given with the option -p as a prefix when creating container names. That means no collision.
Very handy!
For more reading: documentation around project-name option

Docker Compose and execute command on starting container

I am trying to get my head around the COMMAND option in docker compose. In my current docker-compose.yml i start the prosody docker image (https://github.com/prosody/prosody-docker) and i want to create a list of users when the container is actually started.
The documentation of the container states that a user can be made using environment options LOCAL, DOMAIN, and PASSWORD, but this is a single user. I need a list of users.
When reading some stuff around the internet it seemed that using the command option i should be able to execute commands in a starting or running container.
xmpp:
image: prosody/prosody
command: prosodyctl register testuser localhost testpassword
ports:
- "5222:5222"
- "127.0.0.1:5347:5347"
But this seems not to work, i checked to running container using docker exec -it <imageid> bash but the user is not created.
Is it possible to execute a command on a started container using docker-compose or are there other options?
The COMMAND instruction is exactly the same as what is passed at the end of a docker run command, for example echo "hello world" in:
docker run debian echo "hello world"
The command is interpreted as arguments to the ENTRYPOINT of the image, which in debian's case is /bin/bash. In the case of your image, it gets passed to this script. Looking at that script, your command will just get passed to the shell. I would have expected any command you pass to run successfully, but the container will exit once your command completes. Note that the default command is set in the Dockerfile to CMD ["prosodyctl", "start"] which is presumably a long-running process which starts the server.
I'm not sure how Prosody works (or even what it is), but I think you probably want to either map in a config file which holds your users, or set up a data container to persist your configuration. The first solution would mean adding something like:
volumes:
- my_prosodoy_config:/etc/prosody
To the docker-compose file, where my_prosody_config is a directory holding the config files.
The second solution could involve first creating a data container like:
docker run -v /etc/prosody -v /var/log/prosody --name prosody-data prosody-docker echo "Prosody Data Container"
(The echo should complete, leaving you with a stopped container which has volumes set up for the config and logs. Just make sure you don't docker rm this container by accident!)
Then in the docker-compose file add:
volumes_from:
- prosody-data
Hopefully you can then add users by running docker exec as you did before, then running prosodyctl register at the command line. But this is dependent on how prosody and the image behave.
CMD is directly related to ENTRYPOINT in Docker (see this question for an explanation). So when changing one of them, you also have to check how this affects the other. If you look at the Dockerfile, you will see that the default command is to start prosody through CMD ["prosodyctl", "start"]. entrypoint.sh just passes this command through as Adrian mentioned. However, your command overrides the default command, so your prosody demon is never started. Maybe you want to try something like
xmpp:
image: prosody/prosody
command: sh -c prosodyctl register testuser localhost testpassword && prosodyctl start
ports:
- "5222:5222"
- "127.0.0.1:5347:5347"
instead. More elegant and somehow what the creator seems to have intended (judging from the entrypoint.sh script) would be something like
xmpp:
image: prosody/prosody
environment:
- LOCAL=testuser
- DOMAIN=localhost
- PASSWORD=testpassword
ports:
- "5222:5222"
- "127.0.0.1:5347:5347"
To answer your final question: no, it is not possible (as of now) to execute commands on a running container via docker-compose. However, you can easily do this with docker:
docker exec -i prosody_container_name prosodyctl register testuser localhost testpassword
where prosody_container_name is the name of your running container (use docker ps to list running containers).

Resources