diff --git a/slides.md b/slides.md index 297335d..bc0491a 100644 --- a/slides.md +++ b/slides.md @@ -51,17 +51,62 @@ transition: fade-out layout: center --- -## Why Containers? +# Who is this for? -- "It works on my machine" is a thing of the past -- Containers are lightweight and portable -- Boot in milliseconds -- Ideal for reproducible dev environments +## About you +- Some experience with Docker/containers +- Some experience with BASH +- Want to better understand how containers work --- transition: fade-out layout: center --- + +## Follow Along +**Example Repo** - https://git.hackanooga.com/mikeconrad/demystifying-docker + +--- +transition: fade-out +layout: center +--- + + + +--- +transition: fade-out +layout: center +--- + +## Common Use cases for containers +- Reproducible dev environments +- Testing in CI/CD environments +- Better "Portability" of application code +- Snapshot of application code at specific point in time + + + +--- +transition: fade-out +layout: center +--- + +## How we use containers + +- PR builds (Preview Environments). +
+
+### Allows us to +- Test changes in isolated environments +- Simplify complex dev environment setups + - (frontend/backend services, databases, object storage, etc) + + +--- +transition: fade-out +layout: center +--- + ## Containers vs Virtual Machines | Feature | VM | Container | @@ -71,7 +116,7 @@ layout: center | Isolation | Strong | Process-level | | Portability | Medium | Very High | -In reality we often use containers and vm's together. Containers run inside of VM's for better security and isolation, especially in cloud and multi tenant environments. +In reality we use containers and vm's together. Containers run inside of VM's for better security and isolation, especially in cloud and multi tenant environments. --- transition: fade-out @@ -80,17 +125,35 @@ layout: center ## What is Docker? -- A tool to build and run containers -- Docker engine runs containers using OS features: - - Namespaces - - cgroups - - Union file systems -- Uses images layered from base -> app code +- Written in GO +- Uses Client/Server model with REST API (`docker cli` and `dockerd`) +- Eco system of tools (Compose, Swarm, etc) +- Public Image Registry (Dockerhub) +- Docker client typically runs on same machine as server but doesn't have to --- transition: fade-out layout: center --- +## What is Docker? + +- A tool to build and run containers +- Containers are exclusive to Linux +- Docker engine runs containers using Linux features like: + - Namespaces + - cgroups + - Union file systems +- Container runs from an image layered with base image and application code + +--- +transition: fade-out +layout: center +--- + +## Common Use Cases +- Reproducible Dev environments (dev containers) +- Preview/PR environments (ephemeral test environments) +- Legacy applications or applications with complex environment setups --- transition: fade-out @@ -99,10 +162,11 @@ layout: center ## Docker Architecture -Docker Engine (Server) <-- REST API --> Docker CLI (Client) +Docker CLI (Client) <-- REST API --> Docker Engine (Server) - + +[https://docs.docker.com/get-started/docker-overview/] --- transition: fade-out @@ -113,7 +177,10 @@ layout: center - **Namespaces**: isolate PID, net, mount, etc. - **cgroups**: control CPU, memory, IO -- **UnionFS**: layered filesystem (AUFS, OverlayFS) +- **UnionFS**: layered filesystem (OverlayFS) + ![UnionFS diagram](https://docs.docker.com/engine/storage/drivers/images/overlay_constructs.webp) @@ -122,6 +189,94 @@ transition: fade-out layout: center --- +## Bind/Volume Mounts + +- 2 most common storage mechanisms +- Different use cases and security implications + +--- +transition: fade-out +layout: center +--- +## Bind Mounts + +- Mounting files/directories from the host machine directly into a container (merged overlayfs layer). +- Processes inside container can modify files on host system. +- Bind mounts are strongly tied to the host +- Best for things like dev containers where you need to mount source code into container and have hot reload, etc. + +## Bind Mount Example +```bash +$ docker run --mount type=bind,src=/home/mikeconrad/projects/example/app,dst=/app,ro nginx # ro for ReadOnly +$ docker run --volume /home/mikeconrad/projects/example/app:/app nginx +``` + + + + + +--- +transition: fade-out +layout: center +--- + +## Volume Mount Example +```bash +$ docker run --name postgrestest \ + --mount type=volume,src=postgresData,dst=/var/lib/postgresql/data \ + -e POSTGRES_PASSWORD=postgres \ + --rm postgres:16 + +$ docker run --name postgrestest \ + --volume postgresData:/var/lib/postgresql/data \ + -e POSTGRES_PASSWORD=postgres \ + --rm postgres:16 +``` +```bash +$ docker volume inspect postgresData +[ + { + "CreatedAt": "2025-06-08T10:39:12-04:00", + "Driver": "local", + "Labels": null, + "Mountpoint": "/var/lib/docker/volumes/postgresData/_data", + "Name": "postgresData", + "Options": null, + "Scope": "local" + } +] +``` + +- Docker creates a volume named postgresData and mounts that directory inside the container. + + +--- +transition: fade-out +layout: center +--- + +## Volume mounts +- Created and managed by the Docker Daemon +- Volume data is stored on host filesystem but managed by Docker. +- Used for persistent data. + + + +--- +transition: fade-out +layout: center +--- + ## Anatomy of a Dockerfile ```dockerfile @@ -133,6 +288,11 @@ COPY . . EXPOSE 3000 CMD ["npm", "start"] ``` +```bash +mikeconrad@pop-os:~/projects/demystifying-docker/examples/react +$ docker build -t react-app . +``` + - Starts with a base image - Copy files and install deps @@ -143,33 +303,35 @@ transition: fade-out layout: center --- -## Dockerfile Best Practices +## Multi Stage builds ```dockerfile -# Stage 1: Build the Go binary -FROM golang:1.24.2-alpine AS builder -# Set working directory inside the build container +# Stage 1 - Define Base image +FROM node:22-alpine AS base +# Stage 2 Install dependencies +FROM base AS install-deps WORKDIR /app -COPY go.mod ./ -RUN go mod download +COPY package*.json /app/ +RUN yarn +# Stage 3 Development +FROM install-deps AS develop +WORKDIR /app +COPY --from=install-deps /app/node_modules /app/node_modules COPY . . -# Build the Go binary statically -RUN CGO_ENABLED=0 GOOS=linux go build -o docker-api-proxy . -# Stage 2: Run binary in minimal container -FROM scratch -# Copy binary from builder -COPY --from=builder /app/docker-api-proxy /usr/local/bin/docker-api-proxy -# Run binary -ENTRYPOINT ["docker-api-proxy"] -EXPOSE 80 +ENTRYPOINT ["yarn", "dev", "--host=0.0.0.0"] +EXPOSE 5173 ``` -- Use specific versions, not `latest` -- Combine commands to reduce layers -- Use `.dockerignore` -- Prefer slim or alpine images -- Run as non-root user if possible - +```bash +$ docker build -t react . +$ docker run --rm -P react +``` + --- transition: fade-out layout: center @@ -180,64 +342,26 @@ layout: center - Define multi-container apps in one file - Great for local dev and staging (and production!) -```yaml -name: traefik_secure -services: - socket-proxy: - image: git.hackanooga.com/mikeconrad/docketproxy:latest - container_name: socket-proxy - networks: - - traefik - - socket_proxy - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - read_only: true - security_opt: - - no-new-privileges:true - cap_drop: - - ALL - restart: unless-stopped - environment: - - ALLOWED_NETWORKS=traefik_secure_traefik - traefik: - image: traefik:latest - container_name: traefik - command: - - "--log.level=INFO" - - "--entrypoints.web.address=:80" - - "--entrypoints.websecure.address=:443" - - "--providers.docker=true" - - "--providers.docker.endpoint=tcp://socket-proxy:8000" - - "--providers.docker.exposedbydefault=false" - - "--entrypoints.traefik.address=:8080" - - "--api.insecure=true" - - "--api.dashboard=true" - labels: - - "traefik.enable=true" - - "traefik.http.routers.api.rule=Host(`traefik.docker.localhost`)" - - "traefik.http.routers.api.entrypoints=web" - - "traefik.http.routers.api.service=api@internal" - ports: - - "80:80" - - "8080:8080" - networks: - - traefik - - socket_proxy - depends_on: - - socket-proxy - restart: unless-stopped - whoami: - image: traefik/whoami - networks: - - traefik - labels: - - "traefik.enable=true" - - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" - - "traefik.http.routers.whoami.entrypoints=web" -networks: - traefik: {} - socket_proxy: - driver: bridge - internal: true - enable_ipv6: false -``` +--- +transition: fade-out +layout: center +--- + +## Q/A + +- + +--- +transition: fade-out +layout: center +--- + +## Resources +- [Slide Deck (including examples)](https://git.hackanooga.com/mikeconrad/demystifying-docker-v2) +- [DocketProxy (Docker socket proxy)](https://git.hackanooga.com/mikeconrad/docketproxy) +- [SlimToolkit (Optimize and secure containers)](https://github.com/slimtoolkit/slim) + +## VSCode plugins +https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker +https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers +https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-containers \ No newline at end of file