Dockerfile Ubuntu: Przewodnik dla początkujących deweloperów

目次

1. Wstęp

Czym są Docker i Dockerfile?

W ostatnich latach Docker szybko zyskał popularność jako środek do uproszczenia konfiguracji środowisk deweloperskich i wdrażania aplikacji. Docker ma unikalną zdolność do pakowania aplikacji i jej zależności w pojedynczy „kontener”, który może być uruchamiany w tym samym środowisku w dowolnym miejscu. Aby zbudować ten kontener Docker, niezbędny jest plan o nazwie „Dockerfile”. Dockerfile to plik tekstowy, który określa obraz bazowego systemu operacyjnego, oprogramowanie do zainstalowania, ustawienia zmiennych środowiskowych i więcej. Deweloperzy mogą użyć tego pliku do automatycznego budowania spersonalizowanych środowisk.

Powody wyboru Ubuntu jako bazy

Podczas tworzenia Dockerfile pierwszym krokiem jest określenie obrazu bazowego systemu operacyjnego. Spośród wielu opcji Ubuntu jest szczególnie popularne. Ubuntu to dystrybucja Linuksa oparta na Debianie, znana z łatwości użycia i elastyczności w budowaniu różnorodnych środowisk dzięki obszernej bazie pakietów. Dockerfile oparty na Ubuntu oferuje następujące zalety:

  • Dostępna jest obfita oficjalna i społecznościowa dokumentacja, co skutkuje niższą krzywą uczenia.
  • Wiele pakietów i narzędzi można łatwo zainstalować za pomocą APT (Advanced Package Tool).
  • Oficjalnie dostarczane są lekkie minimalne obrazy (takie jak ubuntu:20.04 , ubuntu:24.04 ).

Cel i grupa docelowa tego artykułu

W tym artykule skupimy się na słowie kluczowym „Dockerfile Ubuntu” i zapewnimy łatwe do zrozumienia wyjaśnienie dla początkujących na temat tworzenia Dockerfile opartych na Ubuntu. Szczegółowo omówimy wszystko, od podstawowej struktury Dockerfile po kroki do faktycznego budowania środowiska Ubuntu, przykłady instalowania środowisk aplikacji jak Python oraz częste błędy z ich rozwiązaniami. Ten artykuł jest polecany dla:

  • Osób, które chcą po raz pierwszy zbudować środowisko za pomocą Dockerfile.
  • Osób, które chcą stworzyć powtarzalne środowisko deweloperskie na Ubuntu.
  • Osób, które chcą pogłębić swoją wiedzę, w tym jak rozwiązywać problemy.

2. Podstawowa struktura Dockerfile

Czym jest Dockerfile? Zrozumienie jego roli

Dockerfile to jak przepis na tworzenie obrazu Docker. Konkretnie, to plik tekstowy, który opisuje, który bazowy system operacyjny użyć, jakie oprogramowanie zainstalować i jakie konfiguracje zastosować. Poprzez wykonanie polecenia docker build za pomocą tego pliku, możesz łatwo zbudować wysoce powtarzalne środowiska deweloperskie i wykonywania aplikacji. Korzyści z używania Dockerfile:

  • Automatyzacja konfiguracji środowiska (brak potrzeby odtwarzania kroków ręcznych).
  • Eliminuje niespójności środowiskowe podczas rozwijania z wieloma członkami zespołu.
  • Łatwo integruje się z potokami CI/CD.

Powszechnie używane podstawowe instrukcje (dyrektywy) w Dockerfile

Dockerfile zawiera kilka instrukcji (dyrektyw), z których następujące są najbardziej reprezentatywne. Połączymy je odpowiednio, aby stworzyć Dockerfile oparty na Ubuntu.

InstructionDescription
FROMSpecifies the base Docker image. Example: FROM ubuntu:24.04
RUNExecutes shell commands. Used for package installation, etc.
COPYCopies local files into the image.
ADDSimilar to COPY, but also allows fetching from URLs and extracting archives.
WORKDIRSets the working directory.
ENVSets environment variables.
CMDDefines the command to be executed when the container starts (can be overridden).
ENTRYPOINTSimilar to CMD, but defines a command that is always executed.

Minimalny przykład Dockerfile opartego na Ubuntu

Poniżej znajduje się bardzo podstawowy przykład Dockerfile opartego na Ubuntu.

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y
    curl
    vim

CMD ["/bin/bash"]

Ten Dockerfile jest skonfigurowany do użycia Ubuntu 24.04 jako bazy, zainstalowania dwóch narzędzi (curl i vim) oraz ostatecznie uruchomienia powłoki bash.

O wyborze tagów Ubuntu

Obrazy Docker Ubuntu są dostępne w oficjalnym repozytorium Docker Hub. Chociaż określenie ubuntu:latest użyje najnowszej wersji, zaleca się jawne przypinanie wersji. Na przykład:

  • ubuntu:22.04 (LTS: wersja z długoterminowym wsparciem, podkreśla stabilność)
  • ubuntu:24.04 (Najnowszy kandydat LTS, podkreśla funkcje)

Rozważ, czy priorytetyzować stabilność czy nowe funkcje w zależności od celu.

3. Praktyka: Tworzenie Dockerfile opartego na Ubuntu

Instalowanie niezbędnych pakietów dla środowiska Ubuntu

Gdy budujesz środowisko Ubuntu za pomocą Dockerfile, często będziesz musiał zainstalować dodatkowe pakiety. Na przykład, następujące narzędzia są powszechnie używane do konfiguracji środowiska deweloperskiego:

  • curl : Do pobierania plików i sprawdzania API.
  • vim : Prosty edytor tekstu.
  • git : Narzędzie do kontroli wersji.
  • build-essential : Zbiór podstawowych narzędzi niezbędnych do kompilacji programów w C/C++.

Aby zainstalować te pakiety w Dockerfile, użyj instrukcji RUN.

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y
    curl
    vim
    git
    build-essential

Uruchamiając najpierw apt-get update, zapewniasz, że najnowsze listy pakietów zostaną pobrane przed instalacją.

Konfigurowanie instalacji nieinteraktywnej

W Ubuntu polecenie apt-get install może wymagać wprowadzenia danych przez użytkownika, ale operacje interaktywne nie są możliwe podczas procesu budowania Dockera. Dlatego zaleca się ustawienie zmiennej środowiskowej w następujący sposób, aby wykonać instalację w trybie nieinteraktywnym.

ENV DEBIAN_FRONTEND=noninteractive

To pozwoli pominąć monity, takie jak „Ustawienia regionalne”, które pojawiają się podczas konfiguracji pakietów, umożliwiając płynne przeprowadzenie instalacji.

Redukcja rozmiaru obrazu poprzez usuwanie niepotrzebnego bufora

Podczas używania APT pobierane pliki tymczasowe (bufor) mogą pozostać w obrazie, co zwiększa rozmiar końcowego obrazu Dockera. Możesz zmniejszyć rozmiar obrazu, usuwając ten bufor w następujący sposób:

RUN apt-get update && apt-get install -y
    curl
    vim
    && rm -rf /var/lib/apt/lists/*

Poprzez łączenie wielu poleceń w jedną instrukcję RUN w ten sposób, możesz również zapobiec tworzeniu niepotrzebnych warstw.

Najlepsze praktyki: Organizacja Dockerfile

W rzeczywistych środowiskach deweloperskich zaleca się następujące najlepsze praktyki pisania Dockerfile:

  • Łącz instrukcje RUN w jak największym stopniu, aby zmniejszyć liczbę warstw.
  • Definiuj wersje i konfiguracje jawnie za pomocą ENV.
  • Używaj komentarzy, aby jasno określić cel każdej operacji.
  • Używaj rm i --no-install-recommends, aby uniknąć pozostawiania niepotrzebnych plików.

Przykład:

RUN apt-get update && apt-get install -y --no-install-recommends
    curl
    git
    && rm -rf /var/lib/apt/lists/*

Dzięki temu możesz zbudować lżejszy i łatwiejszy w utrzymaniu Dockerfile.

4. Budowanie i weryfikacja obrazu Dockera

Budowanie obrazu Dockera z Dockerfile

Po napisaniu Dockerfile następnym krokiem jest zbudowanie obrazu Dockera. Wykonuje się to za pomocą polecenia docker build. Uruchom następujące polecenie w katalogu, w którym znajduje się twój Dockerfile:

docker build -t my-ubuntu-image .
  • Opcja -t służy do nadania nazwy (tagu) obrazowi. W tym przykładzie nadajemy mu nazwę my-ubuntu-image.
  • . odnosi się do bieżącego katalogu, w którym znajduje się Dockerfile.

Po uruchomieniu tego polecenia Docker odczyta sekwencyjnie instrukcje w Dockerfile i zbuduje nowy obraz odpowiednio.

Weryfikacja zbudowanego obrazu Dockera

Po zakończeniu tworzenia obrazu możesz go zweryfikować za pomocą następującego polecenia:

docker images

To wyświetli listę obrazów Dockera istniejących lokalnie i pozwoli sprawdzić następujące informacje:

  • REPOSITORY (nazwa obrazu)
  • TAG (tag)
  • IMAGE ID (unikalny identyfikator)
  • CREATED (data i czas utworzenia)
  • SIZE (rozmiar)

Przykład:

REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
my-ubuntu-image    latest    abcd1234abcd    5 minutes ago   189MB

To potwierdza, że utworzony przez ciebie obraz został pomyślnie zarejestrowany.

Uruchamianie kontenera Dockera i weryfikacja działania

Aby zweryfikować, czy utworzony obraz działa poprawnie, uruchommy kontener Dockera. Użyj następującego polecenia:

docker run -it my-ubuntu-image
  • Określenie opcji -it pozwala na uruchomienie terminala w trybie interaktywnym.
  • Jeśli uruchomi się pomyślnie, pojawi się prompt bash w kontenerze, i będziesz w stanie, jakbyś zalogował się do środowiska Ubuntu.

W kontenerze możesz wykonać polecenia takie jak poniższe, aby sprawdzić, czy zainstalowane narzędzia działają poprawnie:

curl --version
vim --version

Jeśli nie ma problemów, Dockerfile został napisany pomyślnie.

Czyszczenie niepotrzebnych obrazów i kontenerów

W miarę powtarzania budów i eksperymentów, niepotrzebne obrazy Docker i kontenery mogą gromadzić się lokalnie. Zaleca się okresowe ich czyszczenie za pomocą poleceń takich jak poniższe:

  • Usuwanie zatrzymanych kontenerów:
    docker container prune
    
  • Usuwanie nieużywanych obrazów:
    docker image prune
    
  • Usuwanie wszystkich nieużywanych danych (Uwaga!):
    docker system prune
    

Te operacje pomagają oszczędzać miejsce na dysku i zapobiegać problemom.

5. Zastosowanie: Budowanie środowiska Python

Uczynienie Pythona użytecznym w Dockerfile opartym na Ubuntu

Poprzez dodanie środowiska wykonawczego Pythona podczas budowania środowiska Ubuntu za pomocą Dockerfile, możesz wspierać szeroki zakres zastosowań, takich jak rozwój, testowanie i uczenie maszynowe. Chociaż Ubuntu może mieć preinstalowanego Pythona, powszechną praktyką jest jawne budowanie go samodzielnie z perspektywy zarządzania wersjami i pakietami.

Jak zainstalować Python za pomocą apt

Najprostszy sposób to instalacja Pythona za pomocą pakietów APT. Oto przykład:

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y
    python3
    python3-pip
    && rm -rf /var/lib/apt/lists/*

Za pomocą tej metody możesz używać stabilnej wersji Pythona zainstalowanej w systemie (zazwyczaj Python 3.10 lub 3.12 itp.). Ponadto możesz dodawać pakiety Pythona za pomocą polecenia pip.

Zarządzanie wersjami Pythona za pomocą pyenv

Jeśli chcesz używać konkretnej wersji Pythona lub przełączać się między wieloma wersjami, korzystanie z pyenv jest wygodne. Poniżej znajduje się przykład użycia pyenv do zainstalowania Pythona 3.11.6 w Dockerfile:

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y
    git
    curl
    make
    build-essential
    libssl-dev
    zlib1g-dev
    libbz2-dev
    libreadline-dev
    libsqlite3-dev
    wget
    llvm
    libncurses5-dev
    libncursesw5-dev
    xz-utils
    tk-dev
    libffi-dev
    liblzma-dev
    && rm -rf /var/lib/apt/lists/*

# Install pyenv
RUN git clone [https://github.com/pyenv/pyenv.git](https://github.com/pyenv/pyenv.git) ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# Install a specific Python version
RUN pyenv install 3.11.6 && pyenv global 3.11.6

To pozwala na bardziej elastyczne budowanie i zarządzanie środowiskiem Pythona.

Zarządzanie pakietami za pomocą requirements.txt

W rzeczywistych projektach często będziesz potrzebować wielu bibliotek Pythona. requirements.txt służy do zarządzania nimi. Najpierw przygotuj plik requirements.txt w katalogu głównym swojego projektu:

flask==2.3.2
requests>=2.25.1
pandas

Następnie opisz to w Dockerfile w następujący sposób:

COPY requirements.txt /app/requirements.txt
WORKDIR /app

RUN pip install --no-cache-dir -r requirements.txt

To pozwala na zainstalowanie niezbędnych bibliotek naraz, zwiększając powtarzalność twojego środowiska deweloperskiego.

Najlepsze praktyki

  • Podczas używania Pythona, budowanie środowiska wirtualnego za pomocą virtualenv lub venv może pomóc zapobiec konfliktom zależności.
  • Możesz zmniejszyć rozmiar obrazu Docker, usuwając pamięć podręczną ( --no-cache-dir ).
  • Instalacja najnowszej wersji pip za pomocą pip install --upgrade pip przed instalacją pakietów Pythona może zapobiec błędom.

6. Powszechne problemy i rozwiązania

Błędy uprawnień

Przykład:

Permission denied

To występuje, gdy skopiowany plik nie ma uprawnień do wykonywania lub gdy właściciel/pliku/uruchamiający użytkownik nie jest odpowiedni.

Rozwiązania:

  • Ustaw plik jako wykonywalny:
    RUN chmod +x script.sh
    
  • Zmień użytkownika, jeśli to konieczne:
    RUN chown root:root /path/to/file
    

Pakiet nie został znaleziony lub nie może zostać zainstalowany

Przykład:

E: Unable to locate package xxx

Ten błąd pojawia się, gdy nie uruchomiono apt-get update lub podano nieprawidłową nazwę pakietu.

Rozwiązania:

  • Zawsze wykonuj apt-get update przed install :
    RUN apt-get update && apt-get install -y curl
    
  • Sprawdź nazwę pakietu pod kątem literówek i upewnij się, że jest poprawna.

Błędy związane z siecią

Przykład:

Temporary failure resolving 'deb.debian.org'

Ten typ błędu występuje, gdy rozwiązywanie DNS nie powodzi się podczas procesu budowania.

Rozwiązania:

  • Ponowne uruchomienie demona Docker może rozwiązać problem:
    sudo systemctl restart docker
    
  • Przejrzyj ustawienia DNS Dockera (dodaj specyfikacje DNS do /etc/docker/daemon.json ):
    {
      "dns": ["8.8.8.8", "8.8.4.4"]
    }
    

Budowanie pozostaje w starej wersji z powodu efektów pamięci podręcznej

Docker używa pamięci podręcznej warstwa po warstwie w celu przyspieszenia. W rezultacie, nawet jeśli zmodyfikujesz Dockerfile, może on nie budować się zgodnie z oczekiwaniami, ponieważ ponownie wykorzystywane są zbuforowane warstwy.

Rozwiązanie:

  • Przebuduj bez użycia pamięci podręcznej:
    docker build --no-cache -t my-image .
    

Polecenie startowe w kontenerze nie wykonuje się lub kończy natychmiast

Przyczyny:

  • Polecenie określone w CMD lub ENTRYPOINT napotyka błąd.
  • Nawet jeśli w CMD podasz `[„/ zakończy się ono natychmiast, jeśli nie zostanie uruchomione interaktywnie.

Rozwiązania:

  • Uruchom kontener w trybie debugowania i sprawdź:
    docker run -it my-image /bin/bash
    
  • Zrozum różnicę między CMD a ENTRYPOINT i używaj ich odpowiednio do swojego celu.

Doświadczając tych problemów, Twoje umiejętności projektowania Dockerfile z pewnością się poprawią. Gdy napotkasz problem, spokojnie przeczytaj komunikat błędu i dokładnie prześledź, która warstwa lub instrukcja przyczyną.

7. Zakończenie

Potwierdzenie kluczowych punktów przy tworzeniu Dockerfile opartych na Ubuntu

W tym artykule wyjaśniliśmy krok po kroku, od podstaw po zastosowania, jak zbudować środowisko Ubuntu przy użyciu Dockerfile. Powtórzmy tutaj najważniejsze kwestie.

  • Zrozumienie podstawowej struktury Dockerfile to pierwszy krok. Możesz zautomatyzować konfigurację środowiska, łącząc instrukcje takie jak FROM, RUN, CMD i ENV.
  • Ubuntu jest stabilnym i bardzo elastycznym obrazem bazowym. Jego bogate repozytorium paków, duża baza użytkowników oraz dostępność wersji LTS sprawiają, że jest idealnym fundamentem dla środowisk deweloperskich.
  • Możesz instalować niezbędne narzędzia i biblioteki poprzez praktyczne zarządzanie pakietami. Znajomość użycia apt-get, usuwania pamięci podręcznej i instalacji nieinteraktywnych to kluczowe elementy.
  • Budowanie praktycznych środowisk, jest również możliwe przy pomocy Dockerfile. Narzędzia takie jak pyenv, pip i requirements.txt umożliwiają tworzenie wysoce powtarzalnych środowisk deweloperskich.
  • Umiejętności rozwiąwania problemów bezpośrednio przekładają się na stabilną pracę. Zrozumienie typowych pułapek, takich jak problemy z uprawnieniami, kwestie sieciowe i pamięć podręczna budowania, może znacząco zwiększyć efektywność pracy.

Kolejne kroki w nauce Dockerfile

Umiejętność pracy z Dockerfile pozwala wspierać szeroki zakres zastosowań, nie tylko w rozwoju, ale także w testowaniu i wdrażaniu do środowisk produkcyjnych. W dalszej nauce warto przejść do następujących tematów:

  • Zarządzanie konfiguracjami wielokontenerowymi przy użyciu Docker Compose.
  • Integracja z narzędziami CI/CD (GitHub Actions, GitLab CI, itp.).
  • Współpraca z narzędziami orkiestracji kontenerów, takimi jak Kubernetes.

8. FAQ (Najczęściej Zadawane Pytania)

P1. Którą wersję Ubuntu powinienem wybrać w moim Dockerfile?

A1. Zasadniczo, jeśli priorytetem jest stabilność i długoterminowe wsparcie, powszechnie wybiera się wersję LTS (Long Term Support). Na przykład ubuntu:22.04 i ubuntu:20.04 są używane w wielu środowiskach dewelopers i można z nich korzystać z pewnością dzięki 5‑letniemuowi wsparcia.
Z drugiej strony, jeśli chcesz korzystać z najnowszych pakietów i wersji języków, możesz wybrać nowsze wydanie, takie jak ubuntu:24.04, ale zalecamy przetestowanie go wcześniej.

Q2. Dlaczego pojawia się komunikat „Package not found” przy użyciu apt-get install?

A2. Najczęstszą przyczyną jest brak wcześniejszego uruchomienia apt-get update. Jeśli spróbujesz zainstalować pakiet bez odświeżenia listy, otrzymasz błąd, ponieważ odpowiedni pakiet nie zostanie znaleziony w przestarzałej liście.
Poprawny przykład użycia:

RUN apt-get update && apt-get install -y curl

Również zwracaj uwagę na literówki w nazwach pakietów oraz przestarzałe nazwy pakietów (np. python3 zamiast python).

Q3. Jak ustawić zmienne środowiskowe w Dockerfile?

A3. Zmienne środowiskowe ustawia się za pomocą instrukcji ENV. Ta zmienna będzie dostępna zarówno podczas budowania obrazu, jak i w czasie działania kontenera.
Przykład:

ENV DEBIAN_FRONTEND=noninteractive

Jest to typowe ustawienie używane do wyłączania interaktywnych podpowiedzi podczas instalacji APT. Służy także do definiowania konfiguracji aplikacji oraz kluczy API w Dockerfile.

Q4. Jaka jest różnica między CMD a ENTRYPOINT w Dockerfile?

A4. Obie instrukcje określają polecenia, które mają być wykonane przy uruchomieniu kontenera, ale różnią się sposobem użycia i zachowaniem.

ItemCMDENTRYPOINT
OverridableCan be overridden by the docker run commandBasically not overridden (treated as arguments)
UsageSets the default execution commandDefines a command that should always be executed

Przykład:

CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]

W drugim przypadku możesz przekazać CMD jako argument w formie docker run my-image another_script.py.

Q5. Edytowałem mój Dockerfile, ale zmiany nie są widoczne. Dlaczego?

A5. Docker używa pamięci podręcznej podczas procesu budowania, więc nawet przy małych zmianach w Dockerfile mogą być użyte zbuforowane warstwy.
Rozwiązanie:

docker build --no-cache -t my-image .

Spowoduje to wykonanie nowego budowania bez użycia pamięci podręcznej, a wszystkie zmiany zostaną uwzględnione.

侍エンジニア塾