Docker is een cross-platform tool, maar in de praktijk blijkt dezelfde docker-compose configuratie niet vlekkeloos op zowel MacOS, Windows als Linux te werken. In deze blog leg ik uit hoe je er voor kan zorgen dat je docker-composer configuratie cross-platform te gebruiken is.
De bestanden voor deze blog (inclusief docker-compose.yml) is cross-platform te gebruiken en is gehost op Github.
Docker-compose op MacOS
Ik maak zelf gebruik van Docker containers op MacOS. Hoewel het zeker uitdagingen heeft (waaronder performance problemen), werkt het goed. Er zijn geen toegangsfouten of permissie aanpassingen nodig om de normale Docker installatie te gebruiken. Goed om te weten: op MacOS gebruiker Docker Hyperkit om een virtuele Linux machine te draaien. Docker draait binnen deze virtuele machine.
Docker-compose op Windows
Als je Docker Desktop gebruikt (zonder Windows container), dan zal je waarschijnlijk geen fouten tegenkomen. Één van onze klanten gebruikt een oude Windows 7 installatie (welke EOL is) en heeft Docker Toolbox. Voor Docker Desktop heb je Windows 10 of later nodig. De reden waarom ik dit noem is omdat Docker Toolbox soms fouten heeft met het delen van de volumes. Als je een oudere Windows versie hebt, dan is het aan te raden om je installatie te updaten.
Docker-compose op Linux
Tot nu toe gaat het vrij goed. Echter, op Linux kan het lastiger zijn om Docker te draaien. Dat is opmerkelijk omdat Docker eigenlijk op Linux draait. Wat performance betreft draait het ook veel beter omdat je geen virtualisatie overhead hebt. Echter, met Linux kan je tegen permissie fouten aanlopen. Als je een proces onder een andere user id hebt lopen, dan kan het zijn dat dit proces geen toegang krijgt of met de verkeerde rechten de bestanden wegschrijft. Dit wordt beter uitgelegd door thaJeztah.
Om dit probleem op te lossen, legt thaJeztah uit dat je de permissies van de bestanden en folder goed moet zetten. Dit is niet een goede oplossing als je developed, want dan moet je na elke aanpassing de permissies goedzetten.
Laten we aannemen dat je onder de gebruiker ubuntu draai met de user id 1000 (je kan dit vinden door de commando id uit te voeren). De oplossing van István Döbrentei’s is om de processen binnen de container met dezelfde user id uit te voeren. Dat kan door de volgende commando in een dockerfile toe te voegen:
RUN usermod -u 1000 www-data
In dit geval nemen we aan dat de gebruiker ubuntu altijd onder de gebruiker id 1000 werkt. Maar, als je het op een andere server of werkplek uitrolt, dan kan de id verschillen.
Verder moet je ontdekken welke gebruikersnaam in de Docker container wordt gebruikt.
Hoe maak je docker-compose cross-platform geschikt
In deze blog zet ik als voorbeeld een PHP + Apache + MySQL installatie neer met Docker. Hier hebben we het volgende voor nodig:
- mysql:5.7.22
- php:7.4-apache
MySQL – bepaal de gebruiker
Deze image heeft geen ps commando, waardoor het achterhalen van de lopende processen lastiger gaat. Je kan dit installeren als procps package, maar in dit geval kan gokken ook werken. De gebruikersnaam is letterlijk mysql.
PHP – bepaal de gebruiker
Vaak draaien webservers met de gebruikersnaam www-data. Voor de zekerheid starten we de image en kijken we welke gebruikersnaam gebruikt wordt. Als je de machine start, dan ontvang je een id van de container.
docker run -d php:7.4-apache
bbab0180d4f2d010ec25247bf0e4eec9f12c8c80fdbbf4be06b3a73bfd81a42b
Gebruik de id in de exec commando om de processen te achterhalen. Gebruik rm om de machine te verwijderen.
# docker exec -it bbab0180d4f2d010ec25247bf0e4eec9f12c8c80fdbbf4be06b3a73bfd81a42b ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.2 83304 24336 ? Ss 10:28 0:00 apache2 -DFOREG
www-data 16 0.0 0.0 83328 6864 ? S 10:28 0:00 apache2 -DFOREG
www-data 17 0.0 0.0 83328 6864 ? S 10:28 0:00 apache2 -DFOREG
www-data 18 0.0 0.0 83328 6864 ? S 10:28 0:00 apache2 -DFOREG
www-data 19 0.0 0.0 83328 6864 ? S 10:28 0:00 apache2 -DFOREG
www-data 20 0.0 0.0 83328 6864 ? S 10:28 0:00 apache2 -DFOREG
root 27 0.0 0.0 7640 2672 pts/0 Rs+ 10:29 0:00 ps aux
# docker stop bbab0180d4f2d010ec25247bf0e4eec9f12c8c80fdbbf4be06b3a73bfd81a42b
# docker rm bbab0180d4f2d010ec25247bf0e4eec9f12c8c80fdbbf4be06b3a73bfd81a42b
Nu weten we zeker dat het de gebruiker www-data is. Je kan deze tip voor vrijwel elke docker image gebruiken.
Maak het cross-platform Dockerfile bestand
Eerst maken we de docker files. Voordat we dat doen, maak de volgende folders:
- docker
- docker/mysql
- docker/php
- mysql_data
- public
In de dockerfile die we aanmaken gebruiken we de originele images, maar met twee toevoegingen. Eerst definiëren we het argument dat user_id de waarde 1000 heeft.
Vervolgens voeren we usermod uit. Deze veranderd het id van de gebruiker binnen de container naar 1000. Het idee hierachter is dat de bestanden dezelfde id’s krijgen als de gebruiker in de host (in dit geval ubuntu). Hierdoor krijg je dus niet de permissie fouten.
docker/mysql/Dockerfile
FROM mysql:5.7.22
MAINTAINER Daniel Koop
ARG user_id=1000
RUN usermod -u $user_id mysql
docker/php/Dockerfile
FROM php:7.4-apache
MAINTAINER Daniel Koop
ARG user_id=1000
RUN usermod -u $user_id www-data
Het docker-compose.yml bestand
De docker-compose.yml die ik gebruik oogt zoals een normaal bestand. Het verwijst naar de dockerfiles, de poorten, de volumes en afhankelijkheid. In dit voorbeeld neem ik aan dat je al bekend bent met hoe docker-compose.yml werkt. Zo niet, dan raad ik vsupalov’s blog blog aan over de docker-compose bestanden.
Bij de dockfile hadden we de optie voor het meegeven van een argument voorbereid. Dit argument kunnen we in de docker-compose.yml meegeven, zodat per installatie éénvoudig de gebruiker id aangepast kan worden.
Om het argument mee te kunnen geven moet de build regel veranderd worden. Wat normaal het volgende zou zijn voor PHP:
build: ./docker/php
wordt het volgende:
build:
context: ./docker/php
args:
user_id: ${USER_ID}
Doe dit voor elke container:
docker-compose.yml
version: '3'
services:
web:
build:
context: ./docker/php
args:
user_id: 1000
image: wedevelopcoffee/php-74-apache
container_name: php
ports:
- "80:80"
- "443:443"
depends_on:
- mysql
volumes:
- "./public:/var/www/html"
mysql:
build:
context: ./docker/mysql
args:
user_id: ${USER_ID}
image: mrkoopie/mysql
container_name: mysql
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=testdb
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=user
- MYSQL_PASSWORD=pass
volumes:
- "./mysql_data:/var/lib/mysql"
Hoe draai je cross-platform docker-composer
Het draaien van docker-compose werkt zoals normaal:
docker-compose up
Als je de images al hebt gebuild voordat je de aanpassingen hebt gemaakt, dan moet je de –build vlag toevoegen. Dit is alleen nodig als je de Dockerfile(s) of userid aanpast.
docker-compose up --build
Waar kan ik mijn container draaien?
Je kan je Docker container publiekelijk draaien op onze high-performance SSD servers. Voor slechts € 3.95 per maand kan je al je virtuele machine draaien. Start vandaag met Docker op je virtuele server.
Conclusie
Je docker installatie is nu cross-platform geschikt! Je kan het bestand verder flexibel maken door een .env bestand te gebruiken. Ook hiervoor heeft Vsupalov.com een goed artikel.