Dockerfile
vollständige Referenz unter dockerdocs - Dockerfile reference
Schlüsselwörter
FROM
- legt das Basisimage fest
FROM ubuntu:20.04
FROM ubuntu
FROM ubuntu:latest
ADD und COPY
- kopieren Dateien oder Verzeichnisse vom Host ins Imagedateisystem
COPY samplesite/ /var/www/html
ADD myfonts.tgz /usr/local/share/texmf
Unterschied: ADD kann zusätzlich auch
- eine URL als Quelle verwenden
- Archivdateien (tar, gz, ...) automatisch entpacken
Beispiel Dockerfile mit ADD
:
Hinweis: Hier funktioniert nur
ADD
, da man Daten von einer URL herunterlädt.
FROM httpd
ADD https://www.gbssg.ch /usr/local/apache2/htdocs/index.html
RUN chmod 755 /usr/local/apache2/htdocs/index.html
Argument | Bedeutung |
---|---|
--chown=<user>:group | funktioniert nur auf Linux-Containern, Festlegung der Eigentümer und der Gruppe im Linux-Zielsystem |
CMD und ENTRYPOINT
- Angabe des Programmes
- dieses wird beim Start eines Containers (mit
docker run
oderdocker start
) ausgeführt
CMD ["executable","param1","param2"]
CMD shellcommand
executable
: vollständiger Pfad des zu ausführenden Programmes
Unterschied mit und ohne eckige Klammern:
- mit Klammern
- direkte Ausführung der ausführbaren Datei
- Beispiel:
CMD ["/script", "param"]
- ohne Klammern
- Ausführung des Befehls mit einer Shell
- wenn keine Shell (unter Linux
/bin/sh
) verfügbar ist, kann der Befehl nicht ausgeführt werden - Beispiel:
CMD ./script param
Beispiel:
CMD ["/bin/ls", "/var"]
CMD echo Hello World!
CMD ["mysqld"]
ENTRYPOINT ["docker-entrypoint.sh"]
Unterschied:
- CMD
- bei
docker run
übergebenes Kommando wird anstelle von CMD ausgeführt
- bei
- ENTRYPOINT
- bei
docker run
übergebenes Kommando wird als weiterer Parameter zu ENTRYPOINT ausgeführt
- bei
RUN
- Befehle
- werden einmalig beim Erstellen des Images mit
docker build
ausgeführt - erzeugen dadurch neuen Image-Layer
RUN apt-get update -y && \
apt-get install -y --no-install-recommends \
subversion \
joe \
vim \
less && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
Empfehlung der Dockerdokumentation
- möglichst viele Befehle in einem RUN-Befehl zusammenfassen, damit nicht für jeden Befehl ein neuer Image-Layer erstellt wird
VOLUME
- definiert Mount Point auf Verzeichnis auf Host oder anderem Container
- gibt Verzeichnisse an, welche im Hostsystem oder in einem anderen Container gemountet werden
- je nachdem, wie der Container gestartet wird, werden die Volumes als unbenannte oder benannte Volumes oder in ein eigenes Verzeichnis eingebunden
Folgendes Beispiel bildet drei Verzeichnisse des Containers auf dem Host ab. Diese Verzeichnisse werden beim Erstellen eines Volumes in diesem gespeichert.
VOLUME ["/data"]
VOLUME ["/var/lib/mysql", "/var/log/mysql"]
ENV
- definiert Umgebungsvariablen
- können bei
docker run
mit einem Wert versehen werden
ENV PORT=3000
Beim Erstellen dieses Images kann mit docker run -e PORT=8000 <image>
der Wert von der Umgebungsvariablen PORT
neu
gesetzt werden.
EXPOSE
- gibt aktive Ports eines Containers an
- nur zur Dokumentation:
- es können auch Ports verwendet werden, welche nicht mit
EXPOSE
angegeben werden
- es können auch Ports verwendet werden, welche nicht mit
- Weiterleitung ist mit
docker run -p 8080:80 <image>
möglich
EXPOSE 1234
LABEL
- Festhaltung von Metadaten zum Image
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
FROM ubuntu:latest
LABEL "website.name"="geeksforgeeks website"
LABEL "website.tutorial-name"="docker"
LABEL website="geeksforgeeks"
LABEL desc="This is docker tutorial with \
geeksforgeeks website"
LABEL tutorial1="Docker" tutorial2="LABEL INSTRUCTION"
USER
- setzt Benutzer für folgenden
RUN
,CMD
undENTRYPOINT
Anweisungen
USER patrick
WORKDIR
- setzt Arbeitsverzeichnis für folgende
RUN
,CMD
,ENTRYPOINT
,COPY
undADD
Anweisungen - nicht existierende Verzeichnisse werden automatisch erstellt
- eigentlich
cd
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Der Befehl pwd
im obigen Beispiel würde /a/b/c
ausgeben.
Beispiele Single Stage Image
Beispiel C-Konsolen-Anwendung
FROM gcc:4.9
WORKDIR /app
COPY . .
RUN gcc -o hello -static hello.c
CMD ["./hello"]
Beispiel C#-Konsolen-Anwendung
FROM mcr.microsoft.com/dotnet/sdk:9.0
COPY . /
RUN ["dotnet", "restore"]
RUN ["dotnet", "publish", "-c", "Release", "-o", "out"]
ENTRYPOINT ["out/project-name"]
Damit es funktioniert, muss eventuell noch die ItemGroup zur .proj
-Datei hinzufügt werden:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs"/>
</ItemGroup>
</Project>
Multistage Image
Ein Multistage Image besteht aus mehreren Images, welche nacheinander erstellt werden
und welche Daten dann an das nächste Image weitergeben.
Alle diese Images befinden sich nacheinander im gleichen Dockerfile
.
Am Schluss wird nur das letzte Image endgültig erstellt und die Daten der vorherigen werden gelöscht.
Dies ermöglicht das Vorbereiten von Dateien in vorherigen Images, damit das End-Image dann kompakter ist.
Beispiel C-Konsolen-Anwendung
FROM gcc:4.9 AS build
COPY . .
RUN gcc -o hello -static hello.c
FROM scratch AS runtime
COPY --from=build /hello /
CMD ["/hello"]
Beispiel C#-Web-Anwendung
ENTRYPOINT
muss auf die DLL zeigen, die gestartet werden sollWORKDIR
sollte besser explizit gesetzt werden, damit die Applikation auch wirklich im richtigen Verzeichnis gestartet wird
# first stage for the build of the application
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS dotnet-build
WORKDIR /build
COPY . .
RUN ["dotnet", "restore"]
RUN ["dotnet", "publish", "-c", "Release", "-o", "out"]
# second stage for the runtime
FROM mcr.microsoft.com/dotnet/aspnet:8.0
# or WORKDIR run, the absolut path is better, because it is not dependent on the current working directory of the
WORKDIR /run
COPY --from=dotnet-build /build/out .
# optional: change the default port (8080) for the web server
ENV ASPNETCORE_URLS=http://+:5000
EXPOSE 5000
ENTRYPOINT ["dotnet", "mywebapp.dll"]
LABEL description="Dotnet WebApp with Racer"
LABEL author="Lorin Steiner"
Absolute vs. relative Pfadangabe
im oberen Beispiel:
WORKDIR /run
vs.WORKDIR run
WORKDIR /build
vs.WORKDIR build
Unterschied:
- Ausgabe von
dotnet build -t mywebapp .
mitWORKDIR run
:1 warning found (use docker --debug to expand):
- WorkdirRelativePath: Relative workdir "run" can have unexpected results if the base image changes (line 11) - bei relativer Pfadangabe kann es zu Problemen kommen, wenn das Basis-Image und das Arbeitsverzeichnis geändert wird
Fehlerbehebung
Lösungsvorschläge, falls es nicht funktioniert:
-
alle Ordner, Images und Container löschen, welche mit diesem Beispiel zu tun haben → neu beginnen
-
Ordner des Dotnet-Projektes namens
obj
löschenobj
-Ordner ist im Docker-Image nicht nötig, da er nur für den Build-Prozess gebraucht wirdobj
-Ordner wird bei jedem Build neu im ersten Image/Stage erstellt
-
Im
.proj
-File muss man eventuell auch noch die Haupt-Klasse für den Einstieg definieren:<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
</Project>