Online zetten: niet als root
Hier bouw je op verder: Rechten op bestanden en mappen
Weet je dit niet meer zeker? Lees het terug voordat je verdergaat.
Je container uit les 18 draait nog. Vraag wie je site draait:
docker exec gastenboek whoami
root
Het antwoord is root: je site mag alles in de container. Dat is een risico. Zit er een gat in je code, zoals een bestandsnaam van een bezoeker uit Invoer controleren: een bestandsnaam van een bezoeker, dan kan wie dat gat vindt ook alles. Hij kan je code veranderen, programma's installeren, en zoeken naar een weg uit de container.
Een webserver hoort daarom te draaien als een gewone gebruiker, die zo weinig mag als kan.
Een eigen gebruiker in het image
RUN useradd --system app maakt een gebruiker app zonder wachtwoord en zonder thuismap: niemand logt als hem in. USER app zegt dat alles hierna als app draait, ook de CMD.
Daarom maakt de Dockerfile de map data zelf, en geeft hij hem aan app. Zet na COPY . . deze twee regels:
RUN useradd --system app && mkdir data && chown app data
USER app
&& voert de volgende stap alleen uit als de vorige lukte. Je hele Dockerfile is nu:
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
COPY . .
RUN useradd --system app && mkdir data && chown app data
USER app
CMD ["fastapi", "run", "main.py", "--port", "8000"]
Bouw en start opnieuw, en kijk:
docker rm -f gastenboek
docker build -t gastenboek .
docker run -d --name gastenboek -p 8000:8000 gastenboek
docker exec gastenboek whoami
Met docker exec gastenboek ls -l data zie je je databases, met app als eigenaar. Zet de Dockerfile in git:
git add Dockerfile
git commit -m "Niet als root"
git push
Er gaat iets mis
unable to open database file
Je site start, maar geeft bij sommige pagina's een 500, en in docker logs gastenboek staat:
sqlite3.OperationalError: unable to open database file
Oorzaak: een database staat nog niet in data/, en app mag in /app niets maken. Als root zag je die fout nog niet.
Oplossing: zoek in main.py naar SqliteDict(" zonder data/ erachter, verbeter het, en bouw opnieuw.
Permission denied: 'data'
De container stopt meteen, en docker logs gastenboek eindigt met:
PermissionError: [Errno 13] Permission denied: 'data'
Oorzaak: de Dockerfile maakt de map data niet. Dan probeert os.makedirs("data", exist_ok=True) uit les 18 hem te maken, als app, in de map van root.
Oplossing: zet && mkdir data && chown app data achter useradd in je Dockerfile, en bouw opnieuw.
cannot create directory ‘data’: File exists
mkdir: cannot create directory ‘data’: File exists
Oorzaak: de map data uit je project kwam met COPY . . mee in het image, met je testdatabases erin.
Oplossing: zet data/ in .dockerignore, zoals in les 18, en bouw opnieuw. Je .dockerignore is dan:
.venv
__pycache__
.git
*.db
data/
Opdrachten
Opdracht 1: Investigate - Wat mag app niet?
Probeer als app je code te veranderen: docker exec gastenboek touch main.py. Wat zegt de container? Wat betekent dat voor iemand die een gat in je site vindt?
Antwoord
touch: cannot touch 'main.py': Permission denied
main.py is van root, en app mag hem lezen maar niet veranderen. Vindt iemand een gat in je site, dan kan hij je databases lezen en veranderen, want die zijn van app. Maar je code aanpassen, of iets installeren, lukt hem niet. Dat is minder erg, en het is precies wat je met een eigen gebruiker wilde.
Door naar les 20: je berichten bewaren.