Docker is supposed to be a cross-platform tool. It runs on MacOS, Windows and Linux. You can use the containers everywhere, so it should be cross-platform. No. In practice, Docker is not that easy when you use it cross-platform. In this blog, I will explain our experience of how to make your docker-compose cross-platform compatible on MacOS, Windows and Linux.

The example files for making your docker-compose.yml cross-platform compatible are hosted on Github.

Docker-compose on MacOS

I develop using Docker containers on MacOS. While it certainly has its challenges (e.g. performance issues when sharing volumes), it does work. There are no permissions errors nor modifications required to a regular docker file or the docker-compose file. Good to know: Docker uses Hyperkit to create a virtual machine on your Mac.

Docker-compose on Windows

When you use the Docker Desktop version, it is most likely that you won’t run into issues. However, one of our customers used Windows 7 (which is EOL…) and used Docker toolbox. Because it was Windows 7, for some reason Docker Desktop did not install. The reason why I mention this, is because Toolbox does not have proper support for sharing volumes. Therefore, updating to Docker Desktop is recommended to prevent weird issues like not seeing shared volumes.

Legacy desktop solution. Docker Toolbox is for older Mac and Windows systems that do not meet the requirements of Docker Desktop for Mac and Docker Desktop for Windows. We recommend updating to the newer applications, if possible.


Docker-compose on Linux

So far, all is good with MacOS and Windows (if you use the latest version). In both MacOS and Windows, Docker runs as a virtual machine with Linux. Permission issues are resolved automatically. And here, the problem comes. File system permissions are not automatically resolved. This is by design as explained by thaJeztah.

To overcome deployment issues, thaJeztah explains that you would need to set the correct permissions every time on Linux. This is far from ideal as with every git update you have permission issues and need to fix them again. This solution is not the best solution.

Let’s assume that we have the user ubuntu with the id 1001 (which you can find using the command id). István Döbrentei’s solution is to fix the user id’s by adding the following line, where 1001 is the id of the user that owns the file on the host:

Copy to Clipboard

In this case, we assume that the user that owns the file always is 1001. In reality, this is not the case.

Furthermore, you will need to detect which users are used in the docker container.

How to make the docker-compose file cross-platform

In this explanation I will use an example where we will setup a PHP + Apache + MySQL setup with Docker. For this, we need the following images:

  • mysql:5.7.22
  • php:7.4-apache

MySQL – determine the user

This image does not have the ps command, which could make things a bit tricky. In this case, I made the guess that the user is mysql. You could install procps using apt, but in this case my guess was correct.

PHP – determine the user

Usually, webservers run as www-data. To be sure, we can run the image and check what services are unning.

Copy to Clipboard


A string is returned. Use this to run bash in Docker:

Copy to Clipboard

We have now identified that the user is www-data. You can use this trick for virtually any docker image.

Create the cross-platform Dockerfile

First, we will create the docker files. Before we do that, create the following folder:

  • docker
  • docker/mysql
  • docker/php
  • mysql_data
  • public

The docker files simply use the original images, but have two additions. First, we defined the user_id as 1000. We use the argument (ARG) method for that, since this allows us to change the user_id using the docker-compose file.

Second, we run usermod. This will change the id of the user to $user_id, as defined in the argument.


Copy to Clipboard



Copy to Clipboard

The docker-compose file

The docker-compose file looks like a regular compose file. It refers to the dockerfiles, forwards the ports, sets the volumes and dependencies. In this example, I assume that you are familiar with how docker-compose works. If you do not, check out vsupalov’s blog about docker-compose files.

As mentioned with the dockerfile, we have configured the files to listen to arguments. The only difference is that we have changed the build setting. To pass an argument, we need to change the reference to the dockerfile:

Copy to Clipboard


Copy to Clipboard


We will do this for every container we want to run:


Copy to Clipboard


How to run cross-platform docker-composer

Running the containers is easy and does not work any different than normal:

Copy to Clipboard

If you already have build the images before without the change, make sure to add the –build flag. You will only need to do this when you change the Dockerfile or the user_id.

Copy to Clipboard

Where to host your Docker container?

To host your Docker container publicly, pick up one of our virtual servers. For just € 3.95 per month, you can use your Docker file in production or develop on stable servers. Learn more about virtual servers for Docker.


Congratulations! You have made your docker environment cross-platform proof. You can further extend the flexibility by using a .env file. There is a great article by explaining how you can use a .env file with Docker.