Update slide deck
This commit is contained in:
216
slides.md
216
slides.md
@ -71,7 +71,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
|
||||
@ -81,7 +81,7 @@ layout: center
|
||||
## What is Docker?
|
||||
|
||||
- A tool to build and run containers
|
||||
- Docker engine runs containers using OS features:
|
||||
- Docker engine runs containers using Linux features:
|
||||
- Namespaces
|
||||
- cgroups
|
||||
- Union file systems
|
||||
@ -92,17 +92,13 @@ transition: fade-out
|
||||
layout: center
|
||||
---
|
||||
|
||||
---
|
||||
transition: fade-out
|
||||
layout: center
|
||||
---
|
||||
|
||||
## Docker Architecture
|
||||
|
||||
Docker Engine (Server) <-- REST API --> Docker CLI (Client)
|
||||
|
||||
<img src="https://docs.docker.com/get-started/images/docker-architecture.webp" width="700" />
|
||||
<!--  -->
|
||||
|
||||
[https://docs.docker.com/get-started/docker-overview/]
|
||||
|
||||
---
|
||||
transition: fade-out
|
||||
@ -113,7 +109,10 @@ layout: center
|
||||
|
||||
- **Namespaces**: isolate PID, net, mount, etc.
|
||||
- **cgroups**: control CPU, memory, IO
|
||||
- **UnionFS**: layered filesystem (AUFS, OverlayFS)
|
||||
- **UnionFS**: layered filesystem (OverlayFS)
|
||||
<!--
|
||||
Overlayfs is the default. This allows Docker to use a layered approach. In this example the bottom layer or lowerdir is the "filesytem" from the image. The upperdir is the container filesystem (not persisted by default) and the merged is volume/bind mounts.
|
||||
-->
|
||||
|
||||

|
||||
|
||||
@ -122,6 +121,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 # ro for ReadOnly
|
||||
$ docker run --volume /home/mikeconrad/projects/example/app:dst=/app
|
||||
```
|
||||
<!-- https://docs.docker.com/engine/storage/bind-mounts/ -->
|
||||
|
||||
<!--
|
||||
These terms are oftentimes used interchangebly and can be confusing but it is important to understand the difference.
|
||||
You need to be careful when using bind mounts because by default, the processes running in the container will have read/write access to your filesystem.
|
||||
This could cause some issues if code running inside the container is malicious or is compromised.
|
||||
It is also possible to mount the files as read-only so that the container has access to read them but not write. This is better for security.
|
||||
Bind mounts also "overwrite" the container/image filesystem layers. So for example mounting ./some-files/test:/etc/passwd would overwrite the /etc/passwd file in the container
|
||||
The directory inside the container does not need to exist for this to work. If the directory does not exist inside of the container filesystem it will be created with the contents.
|
||||
-->
|
||||
|
||||
|
||||
---
|
||||
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.
|
||||
<!-- https://docs.docker.com/engine/storage/bind-mounts/ -->
|
||||
|
||||
---
|
||||
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.
|
||||
|
||||
<!--
|
||||
It is possible to modify the data directly via normal tools but unsupported and can cause unintended side-effects due to the overlayfs storage driver.
|
||||
An example would be creating a postgres volume for persistent database storage.
|
||||
-->
|
||||
|
||||
---
|
||||
transition: fade-out
|
||||
layout: center
|
||||
---
|
||||
|
||||
## Anatomy of a Dockerfile
|
||||
|
||||
```dockerfile
|
||||
@ -138,30 +225,31 @@ CMD ["npm", "start"]
|
||||
- Copy files and install deps
|
||||
- Set default command
|
||||
|
||||
```bash
|
||||
$ docker build -t node-app .
|
||||
```
|
||||
---
|
||||
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
|
||||
FROM node:22-alpine AS base
|
||||
FROM base AS build
|
||||
# Set working directory inside the build container
|
||||
WORKDIR /app
|
||||
COPY go.mod ./
|
||||
RUN go mod download
|
||||
COPY package*.json ./
|
||||
RUN yarn
|
||||
|
||||
FROM base AS develop
|
||||
COPY --from=base /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"]
|
||||
EXPOSE 3000
|
||||
```
|
||||
|
||||
- Use specific versions, not `latest`
|
||||
@ -180,64 +268,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
|
Reference in New Issue
Block a user