= Create a Docker Image Thomas W. Stütz 2.0.0, 2023-04-08: How to use docker in project work @ HTL Leonding college ifndef::imagesdir[:imagesdir: images] //:toc-placement!: // prevents the generation of the doc at this position, so it can be printed afterwards :sourcedir: ../src/main/java :icons: font :sectnums: // Nummerierung der Überschriften / section numbering :sectnumlevels: 5 :toc: left :toclevels: 5 :experimental: true :linkattrs: // so window="_blank" will be executed //Need this blank line after ifdef, don't know why... ifdef::backend-html5[] // https://fontawesome.com/v4.7.0/icons/ icon:file-text-o[link=https://raw.githubusercontent.com/htl-leonding-college/docker-lecture-notes/main/asciidocs/{docname}.adoc] ‏ ‏ ‎ icon:github-square[link=https://github.com/htl-leonding-college/docker-lecture-notes] ‏ ‏ ‎ icon:home[link=https://htl-leonding-college.github.io/docker-lecture-notes/] endif::backend-html5[] == Grundlagen * Docker-Images können aus Docker-Registries gepullt werden ** https://hub.docker.com/ ** https://quay.io/search ** uvam * Oft ist es aber sinnvoll ein eigenes Image zu bauen. * Man kann so eine Umgebung für seine Applikation vorkonfigurieren. == Dockerfile * Man benötigt hierzu eine Textdatei mit dem Namen `Dockerfile` (ohne extension) * wie in einem Script kann eine Umgebung für das Programm gebaut werden, dass am Ende im docker-Container laufen wird. * Es gibt hierfür mehrere Kommandos, die wir nun kennenlernen werden. [plantuml,build-image,png,theme=sketchy-outline] ---- @startuml !theme materia cloud "Docker Registry" { artifact "docker\nImage" as img } file Dockerfile as dockerfile artifact "Docker\nImage" as image node "Docker\nContainer" as container img -> dockerfile: FROM dockerfile -> image: docker build image -> container: docker run @enduml ---- * Jedes Kommando ist ein eigener Layer, daher werden RUN - Kommandos oft mit && verbunden, um die Anzahl der Layer zu reduzieren. -> https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#minimize-the-number-of-layers[Minimize the number of layers^] image::dockerfile-kommandos.png[] == FROM * Zum Auswählen des 'Base Images* * Man kann hierfür ein Betriebssystem wählen zB u buntu, alpine oder bereits mit einer Applikation, wie zB nginx, mariadb, postgres, node, ... * gibt man keine docker-registry an, wird automatisch https://hub.docker.com verwendet * Die https://docs.docker.com/engine/reference/builder/#from[Syntax^] des FROM-Kommandos sieht wie folgt aus: + ---- FROM [--platform=] [:] [AS ] ---- .Mögliche Verwendung von FROM [source,dockerfile] ---- FROM openjdk:20-jdk FROM --platform=linux/arm64 20-jdk FROM openjdk:latest FROM openjdk:20-jdk FROM --platform=linux/arm64 eclipse-temurin:20-jammy ---- .HelloWorld.java [source,java] ---- public class HelloWorld { public static void main(String[] args) { System.out.println("Hello world!"); } } ---- == Beispiel 1 [source,dockerfile] ---- FROM openjdk:latest # <.> COPY ./src . # <.> RUN javac HelloWorld.java # <.> CMD java HelloWorld # <.> ---- <.> Nur beim Entwickeln `:latest` verwenden <.> Kopiert alle Files from Ordner ./src in den aktuellen Ordner im Image (root) <.> RUN führt ein Kommando aus <.> CMD ist der eine Befehl, weswegen der Container gestartet wird. .Bauen des Images [source,shell] ---- docker build -t hello-world . ---- .Starten des Containers [source,shell] ---- docker run --name hello-world hello-world:latest ---- .Ansehen des gestoppten Containers [source,shell] ---- docker container ls -a ---- .Löschen des gestoppten Containers [source,shell] ---- docker container rm hello-world ---- == Beispiel 2 * Es wird nur das image gewechselt -> Java auf Ubuntu [source,dockerfile] ---- FROM eclipse-temurin:20-jammy COPY ./src . RUN javac HelloWorld.java CMD java HelloWorld ---- * Nun ist genau festgelegt ** welches JDK verwendet wird -> temurin 20 ** welches OS verwendet wird -> Ubuntu 22.04 LTS Jammy Jellyfish .Bauen des Images [source,shell] ---- docker build -t hello-world . ---- .Starten des Containers [source,shell] ---- docker run --rm \ # <.> --name hello-world hello-world:latest ---- <.> rm ... remove -> der gestoppte Container wird automatisch gelöscht == Beispiel 3 .index.html [source,html] ---- HTL

My Personal Site

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua

---- .Dockerfile [source,dockerfile] ---- FROM ubuntu:22.04 MAINTAINER stuetz RUN apt update RUN apt install -y nginx COPY index.html /usr/share/nginx/index.html EXPOSE 80 ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"] ---- ---- # build the image docker build -t my-webserver:v1.0 . # start the container docker run --rm \ -p 8080:80 \ --name my-web my-webserver:v1.0 ---- * Man würde eher ein fertiges nginx-image verwenden, als es zu bauen. == CMD * Jeder Docker Container führt nur EIN Kommando aus: ** CMD oder ** ENTRYPOINT * Alle .sh files die in `/docker-entrypoint.d` enthalten sind, werden automatisch beim Starten des Containers ausgeführt. [https://www.camptocamp.com/en/news-events/flexible-docker-entrypoints-scripts[source^]] .Dockerfile [source,dockerfile] ---- FROM ... CMD ["tail", "-f", "/dev/null"] ---- * Dieses Kommando verhindert, dass der Docker Container beendet wird.