I do like the basic idea of Docker. However, using it is cumbersome, at least sometimes.
docker-compose seems to offer a great opportunity to start-up a solution which is based on a set of Docker containers. It would be great if it would work in exactly the same manner as docker run. However, it does not seem to do so regarding its networking behaviour.
I have a, unfortunately rather complex solution, where I have a set of containers running. All of them using Thrift communication. Unfortunately, version 12 with no reasonable option to upgrade because it would result in refactoring the whole communication layer. Too, much work for too little time and if I had the time I would replace Thrift all together. So no bashing needed there. However, for now Iām stuck with it.
Reason to rease this issue here is my hope that somebody could give me a hint on where to find a in depth documentation on what docker-compose dose differently rather than docker run when it comes to networking and port mapping. Because what Iām saying is that I do have a show case where I can show that there IS a difference between starting a container using a .yaml file and starting the same (i.e. identical image) with docker run and identical port mapping and parameter passing to the container as the .yaml file suggests. Result is the container started with docker-compose crashes deep in the Thrift dll which the container started with docker run happily works. Ok, yes, mentioning dll means Iām using mono because the solution itself is mainly based on C# and yes .NET. Why then use Thrift? Well, was not my decision. People wanted to be language independent.
So admittingly it is a quite letās challenging melange of technologies and probably not what you would use. However, I would really like to understand the difference between docker-compose and docker run ā¦
Regarding network, the main difference is that compose by default creates custom docker networks or you can also read about it as āuser-defined networkā so each project is isolated from eachother. You could override it, but these user-defined networks are the recommended way even whej using docker run if you want multiole containers to communicate with eachother so you can use their container name (and compose service name in compose) as domain name to access another containerās port instead of using changable IP addresses.
Local firewalls or other security softwares like apparmor, selinux, seccomp could affect how network works and which one works.
If you share your compose file content and the docker run command, we can tell you whether both configurations are truly identical.
The docker cli and the compose plugin of the cli are merely user interfaces that create rest calls that are sent to the same docker api endpoints. I am confident to say that every docker run argument can be directly translated into a compose file configuration and vice versa.
Hi, thanks a lot for your reply. Iāll provide the information. However, it is more complicated than just a yml file and a run command because Iām using .env. Iāll prepare the information for you to look at and you can even try and produce the effect on your own because the images will be available at Docker Hub.
Thanks for your comments. To make things hopefully a bit easier for you, I provide you access to the file test.zip which you should be able to download from
This is not a security breach because everything in there is meant to be open source anway on GitHub and Docker Hub.
Anyway, to do a test you only need to unzip the file test.zip and change to the folder test. In this folder, replace the āIP addressā 0.0.0.0 in the file .env with the IP address of the machine on which you want to do the test. Please note: You need to replace both occurrences of 0.0.0.0.
After this you can first run (meant for CMD or PowerShell in Windows):
docker-compose --env-file=..env -f .\Launcher.yml up
and then in a new window:
docker-compose --env-file=..env -f .\CSharpAdapter.yml up
and see how the container crashes. Safest way to continue is to stop and remove the two containers.
Then start the first one again with:
docker-compose --env-file=..env -f .\Launcher.yml up
and go to the second window and do:
docker run -p 8911:8900 -it mosim01/mosim:csharpadapter 0.0.0.0 8900 8911 0.0.0.0:9009
where again you need to replace the two occurrences of 0.0.0.0 with the IP address of your local machine. Then you should see the CSharpAdapter happily registraing at the Launcher and running.
If you can explain to me, why the CSharpAdapter.yml does not start the CSharpAdapter in the same manner as the given docker run command, I would have learned something new about Docker and docker-compose.
PS: I tried docker compose config CSharpAdapter.yml
However, got the error message that no config file is available and I could not find hints on the net how such a file should look like. On the other hand, I also do not really believe in expanding the variables in the .yml files. I want to use .env as it is and for all images available at mosim01/mosim this actually works except the image for the CSharpAdapter.
Thanks for your help and efforts.
Thank you for preparing it, but to be honest I was more hoping to just see the compose file and the docker run command. Please forgive me If I am not going to look at it.
The docker run command docker run -p 8911:8900 -it mosim01/mosim:csharpadapter 0.0.0.0 8900 8911 0.0.0.0:9009 translates to this compose file:
As your docker run command didnāt have any environments, of course the translation to a compose file doesnāt have any environments as well.
Docker compose always implied the -d argument from docker run, which makes stdin_open:true and tty: true to be irrelevant, if the image is designed correct so that the entry point script starts a foreground process that keeps running, and runs as long as the container is supposed to run,
Please compare for yourself if this is really how you configured your compose file.
Hi I am running my project using docker compose file in visual studio 2022 . Project is .net framework 4.5. i am using windows docker compose file. while running visual studio docker compose the local default browser will open with the first start up container ip and i am getting the result. in docker compose file i am clearly mentions the local port to run the project if i call the local port mentioned in the compose file i did not get the result . it shoe 404 error how to correct the issue . (if port will call it does not work Container IP is call it will work)
docker run command: docker run --rm -d --name nginx -p 80:80 -p 443:443 nginx
You obviously can only run one at a time because they share the same ports, but you can run one a time and then run docker inspect nginx to see its networking.
On the container started with docker compose. you will find a new (for each container) default bridge-driver network. This network has its own subnet range that is different than the docker bridge network. This network is isolated from the other docker networks, but other containers can be attached to this new default bridge-driver network. If you uncomment the network info on the second level of the config file plus network name under the networks section, it works the same way only you have now named the network instead of letting docker created it for you.
On the container started with docker run, you will find the container attached to the docker bridge network sharing the same subnet as the docker0 virtual adapter on the host machine.
I used docker network ls and docker network inspect <network name or ID> to compare the resulting subnets for both containers.
That being said, I tried this with busybox (set to sleep-3600) and it didnāt work out the same way. I even had to play with the compose file to make nginx connect to the network that docker compose created because my docker compose wants to place a prefix_ (in my case I used āmyprojectsā in the example) on my container_network that it creates. I think this is an image + system configuration specific issue that takes some tweaking for each container to make it work according.
I am not exactly sure what you try to say, but all resources in a compose file are prefixed by the project name. If you donāt provide it, docker compose will use the directory name the compose file is located in.
To summarize your observations: the default behavior regarding docker compose and docker run are not always identical. Thatās true.
The reason docker run defaults to the default bridge network is simplicity. The reason docker compose defaults to creating and using user defined networks is superiority. While a user defined bridge network provides built-in dns-based service discovery, the default bridge does not (it relies on links instead). While a container can be attached to multiple user defined networks, the default bridge network is exclusive and does not allow attaching the container to any other network.
If other services set as dependencies, those will run as well. Or you can list all the services as arguments. The only strange thing is that if I do it, only one container will be in the output in docker compose ps without -a even though both are runing.
So it is possible just not with the up subcommand. And I would not use --rm with -d. I only do it sometimes by accident when I test a container interactively and then want to run it in detached mode but forget to remove --rm.
Possible, yes, but not as a YAML configuration, only as a manual command flag.
Now I do get that most of the times you wouldnāt want --rm, especially as a default behavior of something, so it makes sense to use it as a manual-only command flag
Still, it kinda contradicts the whole point of the compose file being made to host all the commadn configurations so that you donāt need to re-enter them manually every time
Docker Compose could be improved. There are strange behaviors like the one I described. Not to mention that compose run does not use the port forward definition of the service from the yaml without specifying it in the command line, but it does use it for the dependencies.
Regarding --rm, I think that is a parameter which does not belong to the service as strictly as other parameters, but there was no name parameter in the past for the compose project in the yaml file, and it is supported since compose v2, so I would not be surprised if more eparameters were implemented in the yaml in the future. Iām still not sure I would ever use a remove: true in the yaml.
Same, remove: true will probably not be useful in most cases - But allowing it may prove beneficial to the Compose project.
Services which run a simple process and then exit, donāt necessarily need to stay stopped.
In a simple-action performing service, Iād rather have a remove: true property in the YAML, and specify --rm false in the off-cases in which I want the container to stay stopped for logs etc.
Is it a reason for implementing it in the yaml file or implementing the missing flag for the up subcommand?
but can be set as you would with docker run using the --name option. So the docker compose run seems like just an alternative to docker run except it can handle dependencies in the compose file. That way we have everything in compsoe we would have with docker run, except that since docker compose up has no alternative in docker run that works differently. and the --rm flag is missing.
Yes, it is a good idea. In fact Iām thinking of splitting this topic since we kind of started to discuss a feature request instead of just the difference between docker compose (up/run) and docker run, but it is still related to the reason of the differences.