Dockerfile dla aplikacji webowej
Zapiszesz instrukcje budowania obrazu prostej aplikacji Python i odróżnisz etap budowy od uruchomienia.
1. Krótka teoria
Dockerfile jest przepisem na obraz, a nie skryptem uruchamianym przy każdym starcie kontenera. FROM wybiera obraz bazowy, WORKDIR ustala katalog roboczy, COPY przenosi pliki z kontekstu budowania, a RUN wykonuje polecenie podczas budowy. CMD określa domyślny proces, który użytkownik może zastąpić argumentami docker run. ENTRYPOINT ustala wykonywalny punkt wejścia; argumenty z CMD mogą być jego domyślnymi parametrami. Dla aplikacji ASGI wystarczy jedno czytelne CMD z Uvicornem. EXPOSE 8000 dokumentuje port wewnątrz obrazu, ale go nie publikuje. ENV nadaje niepoufne wartości domyślne; sekretów nie wolno wpisywać do Dockerfile, bo zostaną utrwalone w obrazie. W ćwiczeniu orders-api ma plik requirements.txt oraz punkt wejścia app.main:app. Uvicorn musi nasłuchiwać na 0.0.0.0 wewnątrz kontenera, aby ruch przez opublikowany port mógł do niego dotrzeć. Następne lekcje poprawią cache i bezpieczeństwo tego prostego obrazu.
2. Przykłady komend
FROM python:3.12-slim
Wybiera bazowy obraz Pythona; w projekcie wersję należy kontrolować.
FROM python:3.12-slim
WORKDIR /srv/orders-api
Ustala katalog dla kolejnych instrukcji.
WORKDIR /srv/orders-api
COPY requirements.txt .
Kopiuje listę zależności z kontekstu do obrazu.
COPY requirements.txt .
RUN python -m pip install --no-cache-dir -r requirements.txt
Instaluje zależności na etapie budowy.
RUN python -m pip install --no-cache-dir -r requirements.txt
COPY app ./app
Kopiuje kod aplikacji po instalacji zależności.
COPY app ./app
ENV PYTHONDONTWRITEBYTECODE=1
Ustawia niepoufną domyślną konfigurację Pythona.
ENV PYTHONDONTWRITEBYTECODE=1
EXPOSE 8000
Dokumentuje wewnętrzny port serwera.
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Definiuje domyślny proces aplikacji w formie exec.
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
ENTRYPOINT ["python"]
Alternatywny wariant Dockerfile: stały program z argumentami w CMD, zamiast wcześniejszego CMD uruchamiającego Uvicorn.
ENTRYPOINT ["python"]
CMD ["-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
3. Zadanie praktyczne
orders-api z plikami requirements.txt i app/main.py. Ułóż instalację zależności przed kopiowaniem kodu, dodaj EXPOSE 8000 i CMD dla Uvicorna. Zbuduj obraz poleceniem docker build -t orders-api:local . i uruchom go z publikacją portu tylko na 127.0.0.1. Sprawdź endpoint przez curl; nie dodawaj haseł do obrazu.
4. Typowe błędy
- Mylenie RUN, wykonywanego przy budowie, z CMD, uruchamianym przy starcie.
- Używanie 127.0.0.1 jako adresu nasłuchu Uvicorna wewnątrz kontenera.
- Zakładanie, że EXPOSE zastępuje publikację portu przez -p.
- Zapisywanie hasła przez ENV lub RUN w warstwach obrazu.
- Kopiowanie kodu przed zależnościami, co niepotrzebnie unieważnia cache instalacji.
5. Podsumowanie
Dockerfile opisuje obraz krok po kroku. FROM, WORKDIR, COPY i RUN budują środowisko, CMD uruchamia proces, a EXPOSE dokumentuje port. Sekrety i konfiguracja środowiska powinny być dostarczane poza obrazem.