ID: I202604231704
Status: idea
Tags: Promptus Imperii, Docker, Docker Compose

Docker workshop PI

Workshop van Frido

de volledige readme van de workshop.

Shit man, nu heb ik honger tijdens de workshop…

Waar gebruik je het?

Docker kom je overal tegen in de SDLC.

  • Requirements: om te prototypen
  • Design: hoe kan je je process inrichten
  • Implementatie: bij de CI/CD
  • Testing: je kan alle testcases makkelijk in docker gooien
  • Evaluation: in productie zie je het ook terugkomen

PhotoManager example

Github repository van de leraar.

alle dingen zijn terug te lezen in de readme in de repo.

Rundown

Op hub.docker.com staan allemaal images die je al kan importeren. Bij projecten zie je ook de CVE’s waar ze in voor komen.

docker run hello-world is een command.

docker run -p 8000:8000 hello-world is om de port 8000 te exposen.

docker build . is om een dockerfile met de naam dockerfile te builden.

docker build -t cool . is om een dockerfile met de naam dockerfile te builden als een image met de naam cool.

docker system df haal je op hoeveel images je hebt etc.

met docker container ls -a kan je al je containers bekijken (door -a ook degenes die niet actief zijn)

docker containers zijn niet persistent wanner je hem update.

touch dockerfile_new is een mooi linux command om een nieuwe dockerfile te maken.

het verschil tussen RUN en CMD is dat RUN gebeurt tijdens het bouwen van een image. CMD kan je overwriten.

je dockerfile kan elke naam hebben, je kan een dockerfile dus ook gwn henk.md noemen en het zal nogsteeds werken.

Dockerfile aanmaken

In principe is het volgende genoeg om een docker container te maken als je docker build -f dockerfile . uitvoert, onthoudt dat je in de goede directory moet zitten:

FROM debian:12-slim

docker run -it 02-building-image:latest /bin/bash kan je dan met de shell in de container praten.

als je een dockerfile wilt met linux packages, stop dit in je dockerfile:

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3

Met de volgende dockerfile gaat hij automatisch naar de Linux terminal. Nu kan je ook gwn docker run -it 02-building-image:latest gebruiken om hem te runnen.

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
CMD [ "/bin/bash" ]

En met de volgende kan je direct een python file runnen:

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
CMD [ "/bin/python3", "main.py" ]

Maar ja, hoe geef je dan je main.py mee? Nou door het volgende te doen (onthoudt dat je relatieve paden hebt en main.py dus in de zelfde root moet zitten als je dockerfile):

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
COPY main.py
CMD [ "/bin/python3", "main.py" ]

Een entrypoint kan je nooit overschrijven (whatever that means).

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
COPY main.py
ENTRYPOINT [ "executable"]
# CMD [ "/bin/python3", "main.py" ] # is overwritable when you run:
# docker run -it 02-building-image:latest /bin/bash

Nu geef je een argument mee aan je build die je kan overwriten. om te zorgen dat je bijv een username en passw mee kan geven. docker run -it 02-building-image:latest --build-arg MAIN=main_new.py

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
ARG MAIN=main.py
COPY ${MAIN}
RUN cp ${MAIN} main.py
CMD [ "/bin/python3", "main.py" ]

Een entrypoint kan je niet met arguments aanpassen, daarvoor heb je env variables. Dit heeft ook voordelen tegenover variables in andere scenarios, zoals dat je hebt op runtime nog kan aanpassen.

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
ENV MAIN=main.py
COPY ${MAIN}
ENTRYPOINT [ "/bin/bash", "-c", "/bin/python3 ${MAIN}"]

of hieronder is een ander voorbeeld van een entrypoint. docker run -it -e TARGET=intel 02-building-image:latest. En ofc kan je de env en arg combinen.

FROM debian:12-slim
RUN apt update
RUN apt install -y nano python3
COPY main_new.py
ENV TARGET=esp32
ENTRYPOINT [ "/bin/bash", "/bin/python3 main_new.py --target ${TARGET}"]

03-webserver

met de volgende dockerfile navigeer je naar de app folder en maak je daar 2 folders aan. als je dus docker build -t websiteee . en dan docker run -p 8000:8000 websiteee dan run je deze mooie website op localhost:8000

FROM python:3.9-slim
 
WORKDIR /app
 
RUN mkdir webfolder01
RUN mkdir webfolder02
 
ENTRYPOINT [ "python", "-m", "http.server", "8000"]

04-volumes

hier was ik blijkbaar niet bij??

05-compilation

met SHELL kies je welke shell je gebruikt. In de volgende dockerfile builden we rust. We gebruiken CMD zodat we die kunnen overwriten en het kunnen gaan runnen instead. docker build -t 05-compilation . en dan docker run -ti -v ./hello-world:/workdir 05-compilation:latest

FROM debian:12-slim
 
WORKDIR /workdir
SHELL ["/bin/bash", "-c"]
RUN apt update
RUN apt install -y curl build-essential
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
 
 
ENV PATH=${PATH}:/root/.cargo/bin
CMD [ "cargo", "build"]
 

06-multistage

hier hebben we 3 dockerfile’s

  • docker build -t 06-multistage-large -f dockerfile-large .
  • docker build -t 06-multistage-multi -f dockerfile-multi .
  • docker build -t 06-multistage-rust-multi -f dockerfile-rust-multi .
  • docker image ls -a

en dan zie je dat de image sizes heel erg verschillen:

IMAGE                                                    ID             DISK USAGE   CONTENT SIZE   EXTRA
05-compilation:latest                                    cca7e29ef467       1.77GB             0B    U   
06-multistage-large:latest                               aec6f6465708        394MB             0B        
06-multistage-multi:latest                               c62f9a0c2ca4       10.7MB             0B        
06-multistage-rust-multi:latest                          53925fb7063b       79.2MB             0B        

07-compose

Docker Compose WHOOOOOP.

services:
 
  web:
    image: 04-webserver-demo:latest
    container_name: python-webserver
    restart: unless-stopped
    ports:
      - 8001:8000
    volumes:
      - ./webserver/web_root:/app # <--- This is a relative path. So it depends where you start the image
      - time_file:/app/time
    depends_on:
      - time-fetcher
 
  time-fetcher:
    build: python-timefetcher
    volumes:
      - time_file:/time/time_file
 
volumes:
  time_file:

maar dit gaat wss niet werken omdat je die image niet hebt (tenzij je stap 4 ff build). maar je kan dit starten met docker compose up en dan weer afsluiten met docker compose down. Wanneer je dit runt zie je dit op localhost:8001

08-networking

services:
 
  web:
    image: 04-webserver-demo:latest
    restart: unless-stopped
    volumes:
      - ./webserver/web_root:/app # <--- This is a relative path. So it depends where you start the image
    networks:
      - between_containers # Only on internal network, NOT reachable from host
 
  proxy:
    image: nginx:alpine
    ports:
      - "8080:80" # Host port -> Proxy
    networks:
      - between_containers
      - to_host # <- Add this so the host can reach it
    volumes:
      - ./proxy/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - web
 
networks:
  between_containers:
    driver: bridge
    internal: true # Blocks external traffic — no internet access
  to_host:
    driver: bridge
  external_between_host_and_proxy:
    # <-- Not used at the moment
    external: true
    driver_opts:
      # pass options to driver for network creation
      com.docker.network.bridge.host_binding_ipv4: 127.0.0.1
 

We hebben nu een mooie proxy. ik weet niet hoe ik dit moet uitleggen, maar ik weet wel dat het werkt ;)

Je wilt netwerken om meerdere containers met elkaar te laten praten. Denk bijvoorbeeld aan een MariaDB container die je API kan berijken, maar het internet niet. Dit is wat ik dus doe met File - mongo-stack.


References