Docker Best Practices
Development and
Production
1 / 44
Why should you be serious
about using it
2 / 44
development:
3 / 44
docker-compose
4 / 44
version: "3"
services:
app:
build: ./app
5 / 44
bring up in 1 command
6 / 44
run as another user
7 / 44
image size
8 / 44
multi-stage builds
9 / 44
FROM gcr.io/connectedcars-staging/connectedcars-node:9.3 as builder
ARG GITHUB_AT
WORKDIR /app
RUN apt-get update && apt-get install -y mysql-client
ADD . /app
RUN yarn global add node-gyp
RUN yarn
ENV NODE_ENV production
RUN npm run compile
RUN rm -rf node_modules && yarn
FROM gcr.io/connectedcars-staging/connectedcars-node-production:9.3
ENV NODE_ENV production
WORKDIR /app
EXPOSE 9000
COPY --from=builder /app .
CMD npm run production
10 / 44
use official images
11 / 44
create your own base
images
12 / 44
don't use latest, use git sha
images are mutable
13 / 44
Continues Integration
14 / 44
Google Cloud Builder
15 / 44
Google Container Registry
16 / 44
overlay network
multiple networks
17 / 44
version: "3"
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
backend:
18 / 44
docker volumes
19 / 44
version: "3"
services:
db:
image: db
volumes:
- data-volume:/var/lib/db
backup:
image: backup-service
volumes:
- data-volume:/var/lib/backup/data
volumes:
data-volume:
20 / 44
service discovery
21 / 44
version: "3"
services:
app:
build: ./app
db:
image: db
22 / 44
limits?
23 / 44
version: '3'
services:
redis:
image: myapp
deploy:
resources:
limits:
cpus: '0.50'
memory: 500M
reservations:
cpus: '0.25'
memory: 200M
24 / 44
Kubernetes for
development?
25 / 44
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kevin-myapp
spec:
selector:
matchLabels:
app: kevin-myapp
replicas: 2 # tells deployment to run 2 pods matching the template
template: # create pods using pod definition in this template
metadata:
labels:
app: kevin-myapp
spec:
containers:
- name: kevin-myapp
image: gcr.io/dd-decaf-cfbf6/kevin-myapp:latest
ports:
- containerPort: 8000
26 / 44
production:
27 / 44
secrets should be files
28 / 44
docker run -v $(pwd)/secrets/db.json:/secrets/db.json myapp
29 / 44
run as read-only
30 / 44
docker run -d -p 80:80 --read-only nginx
31 / 44
seccomp / apparmour
32 / 44
33 / 44
gvisor
Google Container Runtime Sandbox
34 / 44
35 / 44
36 / 44
37 / 44
Jessie Franzelle
https://blog.jessfraz.com/post/containers-security-and-echo-chambers/
38 / 44
$ docker run --rm 
-it 
--security-opt seccomp=/path/to/seccomp/profile.json 
hello-world
39 / 44
demo seccomp
https://docs.docker.com/engine/security/seccomp/#significant-syscalls-blocked-by-the-
default-profile
https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json
40 / 44
Connected Cars
41 / 44
Startup, Serverless...
42 / 44
Summary
bring up in 1 command
read-only
secrets as files
seccomp is power full
43 / 44
kevin.simper@gmail.com
@kevinsimper
44 / 44

Docker Best Practices in development and Production