Docker. For devs.
run
compose
build
RUN
why?
- yet another package manager
- reproducible environment
- isolated and disposable units
docker pull
docker create
docker start
docker run
docker ps
docker exec
docker stop
docker rm
docker run [-a|--attach[=[]]] [--add-host[=[]]] [--blkio-weight[=[BLKIO-WEIGHT]]] [--blkio-weight-device[=[]]] [--cpu-shares[=0]] [--cap-add[=[]]] [--cap-drop[=[]]]
[--cgroup-parent[=CGROUP-PATH]] [--cidfile[=CIDFILE]] [--cpu-count[=0]] [--cpu-percent[=0]] [--cpu-period[=0]] [--cpu-quota[=0]] [--cpu-rt-period[=0]] [--cpu-rt-runtime[=0]] [--cpus[=0.0]]
[--cpuset-cpus[=CPUSET-CPUS]] [--cpuset-mems[=CPUSET-MEMS]] [-d|--detach] [--detach-keys[=[]]] [--device[=[]]] [--device-cgroup-rule[=[]]] [--device-read-bps[=[]]] [--device-read-iops[=[]]]
[--device-write-bps[=[]]] [--device-write-iops[=[]]] [--dns[=[]]] [--dns-option[=[]]] [--dns-search[=[]]] [-e|--env[=[]]] [--entrypoint[=ENTRYPOINT]] [--env-file[=[]]] [--expose[=[]]]
[--group-add[=[]]] [-h|--hostname[=HOSTNAME]] [--help] [--init] [-i|--interactive] [--ip[=IPv4-ADDRESS]] [--ip6[=IPv6-ADDRESS]] [--ipc[=IPC]] [--isolation[=default]]
[--kernel-memory[=KERNEL-MEMORY]] [-l|--label[=[]]] [--label-file[=[]]] [--link[=[]]] [--link-local-ip[=[]]] [--log-driver[=[]]] [--log-opt[=[]]] [-m|--memory[=MEMORY]]
[--mac-address[=MAC-ADDRESS]] [--memory-reservation[=MEMORY-RESERVATION]] [--memory-swap[=LIMIT]] [--memory-swappiness[=MEMORY-SWAPPINESS]] [--mount[=[MOUNT]]] [--name[=NAME]]
[--network-alias[=[]]] [--network[="bridge"]] [--oom-kill-disable] [--oom-score-adj[=0]] [-P|--publish-all] [-p|--publish[=[]]] [--pid[=[PID]]] [--userns[=[]]] [--pids-limit[=PIDS_LIMIT]]
[--privileged] [--read-only] [--restart[=RESTART]] [--rm] [--security-opt[=[]]] [--storage-opt[=[]]] [--stop-signal[=SIGNAL]] [--stop-timeout[=TIMEOUT]] [--shm-size[=[]]] [--sig-proxy[=true]]
[--sysctl[=[]]] [-t|--tty] [--tmpfs[=[CONTAINER-DIR[:OPTIONS]]] [-u|--user[=USER]] [--ulimit[=[]]] [--uts[=[]]] [-v|--volume[=[[HOST-DIR:]CONTAINER-DIR[:OPTIONS]]]] [--volume-driver[=DRIVER]]
[--volumes-from[=[]]] [-w|--workdir[=WORKDIR]] IMAGE [COMMAND] [ARG...]
-it
--interactive --tty
-d
--detach
> docker run --detach \
--name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine--name
if needed later
--rm
dispose immediately
> docker run -d \
--name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine-v
--volume
-p
--publish, not --port ;)
> docker run -d \
--name pgres \
--publish 5432:5432 \
--volume $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine--link
connect containers
--env
environment variables
> docker run -d \
--name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD_FILE=/run/secrets/postgres-passwd \
postgres:10-alpine
> docker run -it --rm \
--link pgres:db \
postgres psql -h db -U postgresimage
registry/owner/name:tag
command
arguments
entry point
> docker run -d \
--name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine
> docker run -it --rm \
--link pgres:db \
postgres psql -h db -U postgres> docker run -d --name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine
> docker run -it --rm \
-p 8081:80 \
-e PGADMIN_DEFAULT_EMAIL=user@domain.com \
-e PGADMIN_DEFAULT_PASSWORD=password \
--link pgres \
dpage/pgadmin4
> docker run -it --rm \
--link pgres \
postgres psql -U postgreswhat's going on

kernel tools (cgroups, namespaces, etc)
docker engine
RUNTIME
base layer
OS layer
framework layer
other layers
IMAGE
R/W layer
process PID 1
CONTAINER
image
- file system snapshot
- immutable
- shared layers
container
- instance of an image
- 1 running process
- R/W layer
peek into container
> sudo ps
> docker attach pgres
> docker exec -it pgres sh
> docker logs pgres
COMPOSE
why?
- run multiple containers
- file is more readable than shell
- natural documentation
- isolated network
> docker run -d --name pgres \
-p 5432:5432 \
-v $PWD/pgdata:/var/lib/postgresql/data \
postgres:10-alpine
> docker run -it --rm \
-p 8081:80 \
-e PGADMIN_DEFAULT_EMAIL=user@domain.com \
-e PGADMIN_DEFAULT_PASSWORD=password \
--link pgres \
dpage/pgadmin4
> docker run -it --rm \
--link pgres \
postgres psql -U postgresversion: '2'
services:
pgres:
image: "postgres:10-alpine"
app:
image: "bigtruedata/sbt:0.13.15-alpine-2.12.3"
volumes:
- ~/.ivy2/:/root/.ivy2
- ./:/app/
command: sbt run
ports:
- "9000:9000"
stdin_open: true
environment:
- DB_URL=jdbc:postgres:pgres:5432/public
docker-compose up
nice details
- --links not required
- relative paths
- extend:
- env_file:
- build:
version: '2'
services:
pgres:
image: "postgres:10-alpine"
app:
build: .
ports:
- "9000:9000"BUILD
why?
- one tool to build them all
- caching
caching!
- stable / reproducible
- fast
- small footprint
Dockerfile
FROM node:9.5.0-alpine
CMD npm test
COPY package.json .
RUN npm install
COPY app.spec.js .
Dockerfile
FROM node:9.5.0-alpine
CMD npm test # 0B cached
COPY package.json . # 320B cached
RUN npm install # 4.36MB, ~3 sec cached
COPY app.spec.js . # 1.33kB
layer cache
Text
layer_payload = sha256(
parent_layer_id,
layer_command,
filesystem_changes,
);
layer_id = layer_payload in store
? store(layer_payload)
: layer(layer_payload, current_timestamp);cache gotchas
- only local layers
- mtime is ignored
- no build-time volumes
build java
sbt stage
docker build . -t myappFROM openjdk:10-jre-slim
EXPOSE 9000
CMD /app/bin/dev-null
COPY ./target/universal/stage /app/
FROM openjdk:10-jre-slim
EXPOSE 9000
CMD /app/bin/dev-null
COPY ./target/universal/stage /app/
FROM openjdk:10-jre-slim
EXPOSE 9000 # 0B cached
CMD /app/bin/dev-null # 0B cached
COPY ./target/universal/stage /app/ # 47MB
FROM bigtruedata/sbt as builder
WORKDIR /build
COPY . .
RUN sbt stage
FROM openjdk:10-jre-slim
EXPOSE 9000
CMD /app/bin/dev-null
COPY --from=builder /build/target/universal/stage /app/
FROM bigtruedata/sbt as builder
WORKDIR /build # 0s cached
COPY . . # 0s
RUN sbt stage # ~6m
FROM openjdk:10-jre-slim
EXPOSE 9000 # 0B cached
CMD /app/bin/dev-null # 0B cached
COPY --from=builder /build/target/universal/stage /app/ # 47MB
FROM gradle:4.5.1-jdk-alpine
WORKDIR /
COPY build.gradle settings.gradle ./
RUN gradle stage
COPY conf conf
COPY app app
RUN gradle stage
RUN rm build/stage/playBinary/lib/devnull*.jar
FROM openjdk:10-jre-slim
CMD /app/bin/playBinary
COPY --from=0 /build/stage/playBinary /app/
COPY --from=0 /build/distributionJars/playBinary/*.jar /app/lib/FROM gradle:4.5.1-jdk-alpine
ENV GRADLE_USER_HOME=.gradle2 #
USER root # 0B cached
WORKDIR / # 0B cached
COPY build.gradle settings.gradle ./ # 661B cached
RUN mkdir conf && touch conf/routes && gradle stage # 188MB cached ~120s
COPY conf conf # 1.9kB cached
COPY app app # 4.5kB
RUN gradle stage # 50MB ~20s
RUN rm build/stage/playBinary/lib/devnull*.jar # 0B
FROM openjdk:10-jre-slim
CMD rm -f /app/RUNNING_PID && /app/bin/playBinary # 0B cached
COPY --from=0 /build/stage/playBinary /app/ # 49MB cached
COPY --from=0 /build/distributionJars/playBinary/*.jar /app/lib/ # 34kB
docker build
like a pro
-
optimize builds
-
don't over-optimize
-
consider custom base images
-
look for " ---> Using cache"
-
docker history [image]
-
docker inspect [image]
tricks and gotchas
beware of VOLUME
FROM gradle
ADD build.gradle .
RUN gradle stage \
&& ls .gradle
RUN ls .gradle
jar/zip
+
mtime
=
cache miss!
java
+
--memory
=
OOM!
add some UI
-v /tmp/.X11-unix:/tmp/.X11-unixFROM gradle:4.5.1-jdk-alpine
ENV GRADLE_USER_HOME=.gradle2 #
USER root # 0B cached
WORKDIR / # 0B cached
COPY build.gradle settings.gradle ./ # 661B cached
RUN mkdir conf && touch conf/routes && gradle stage # 188MB cached ~120s
COPY conf conf # 1.9kB cached
COPY app app # 4.5kB
RUN gradle stage # 50MB ~20s
RUN rm build/stage/playBinary/lib/devnull*.jar # 0B
FROM openjdk:10-jre-slim
CMD rm -f /app/RUNNING_PID && /app/bin/playBinary # 0B cached
COPY --from=0 /build/stage/playBinary /app/ # 49MB cached
COPY --from=0 /build/distributionJars/playBinary/*.jar /app/lib/ # 34kBTHANKS!
Docker. For devs.
By Artem Sinicyn
Docker. For devs.
- 74