| layout | index |
|---|---|
| author | Jens Piegsa |
| title | Docker 1.13 Cheat Sheet |
| summary | Docker Cheat Sheet. Find, Copy and Paste, Anywhere. |
- Union file system (UFS): allows to overlay multiple file systems appearing as a single system whereby equal folders are merged and equally named files hide their previous versions
- Image: a portable read-only file system layer optionally stacked on a parent image
- Dockerfile: used to
buildan image and declare the command executed in the container - Registry: is the place where to
pushandpullfrom named / tagged images - Container: an instance of an image with a writable file system layer on top, virtual networking, ready to execute a single application
- Volume: a directory outside the UFS that can be mounted inside containers for persistent and shared data
- Network: acts as a namespace for containers
- Service: a flexible number of container replicas running on a cluster of multiple hosts
A typical docker workflow:
buildan image based on aDockerfiletagandpushthe image to a registryloginto the registry from the runtime environment topullthe image- optionally
createavolumeor two to provide configuration files and hold data that needs to be persisted runa container based on the imagestopandstartthe container if necessarycommitthe container to turn it into an image (note: makes the image harder to reproduce)- in exceptional situations,
execadditional commands inside the container - to replace a container with an updated version:
pullthe new image from the registrystopthe running container- backup your volumes to be prepared for a potential rollback
runthe newer one by specifying a temporary name- if successful,
removethe old container andrenamethe new one accordingly
docker system dfdocker system prune{: .note} This prompts for confirmation and will remove: all stopped containers, all volumes not used by at least one container, all networks not used by at least one container and all dangling images
docker image buildshows the IDs of all temporary containers and intermediate images- use
docker container run -it IMAGE_IDwith the ID of the image resulting from the last successful build step and try the next command manually
{% raw %}
docker image ls --no-trunc | grep $(docker image inspect -f {{.Id}} IMAGE:TAG)
{% endraw %}docker container run -it ubuntu:14.04 /bin/bashdocker container exec -it CONTAINER /bin/bashdocker container run -u root IMAGEdocker container ls -adocker container top CONTAINERdocker container logs -f --tail=1000 CONTAINERdocker container stop $(docker container ls -q)docker container ls -a -f status=exited | grep -v '\-data *$'| awk '{if(NR>1) print $1}' | xargs -r docker container rmdocker container prunedocker image ls -adocker image prune{% raw %}
docker image history --no-trunc=true $(docker container inspect -f '{{.Image}}' CONTAINER)
{% endraw %}docker container diff CONTAINERdocker container run --rm --volumes-from SOURCE_CONTAINER:ro -v $(pwd):/backup alpine \
tar cvf /backup/backup_$(date +%Y-%m-%d_%H-%M).tar /datadocker container run --rm --volumes-from TARGET_CONTAINER:ro -v $(pwd):/backup alpine \
tar xvf /backup/backup.tar{% raw %}
docker container inspect -f '{{ range .Mounts }}{{ .Name }} {{ end }}' CONTAINER
{% endraw %}{% raw %}
docker container inspect -f '{{ range .Mounts }}{{ .Name }}:{{ .Destination }} {{ end }}' CONTAINER
{% endraw %}- does not work together with container dependencies
docker container cp CONTAINER:FILE /tmp/ && docker container run --name=nano -it --rm -v /tmp:/tmp \
piegsaj/nano nano /tmp/FILE ; \
cat /tmp/FILE | docker container exec -i CONTAINER sh -c 'cat > FILE' ; \
rm /tmp/FILEdocker container run -i -t -p 80:8080 -e WAR_URL=“<http://web-actions.googlecode.com/files/helloworld.war>” \
bbytes/tomcat7echo "postgres_password" | sudo docker container run -i --rm --link db:db -v $PWD:/tmp postgres:8 sh -c ' \
pg_dump -h ocdb -p $OCDB_PORT_5432_TCP_PORT -U postgres -F tar -v openclinica \
> /tmp/ocdb_pg_dump_$(date +%Y-%m-%d_%H-%M-%S).tar'docker container run --rm --volumes-from oc-data -v $PWD:/tmp piegsaj/openclinica \
tar cvf /tmp/oc_data_backup_$(date +%Y-%m-%d_%H-%M-%S).tar /tomcat/openclinica.datadocker container run --rm --volumes-from oc-data2 -v $pwd:/tmp piegsaj/openclinica \
tar xvf /tmp/oc_data_backup_*.tar{% raw %}
docker container inspect -f '{{ .NetworkSettings.IPAddress }}' CONTAINER
{% endraw %}At the time of writing, there is no way to reconstruct the exact run command that was used to create a container. However, there are third-party tools like runlike that attempt to reverse engineer all parameter values:
docker container run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike CONTAINER{: .note} Caution, the output also contains some implicitly added parameters, that were not used in the original command line. So please evaluate all of them with care.
RUN mkdir /data && echo "some content" > /data/file && chown -R daemon:daemon /data
VOLUME /data
{: .note}
after the VOLUME directive, its content can not be changed within the Dockerfile
docker container run -it -v /data debian /bin/bashdocker container run --rm -v /tmp:/data debian ls -RAlph /datadocker volume create --name=test
docker container run --rm -v test:/data alpine sh -c 'echo "Hello named volumes" > /data/hello.txt'
docker container run --rm -v test:/data alpine sh -c 'cat /data/hello.txt'docker container run --rm -v data:/data alpine ls -RAlph /dataecho "debug=true" > test.cnf && \
docker volume create --name=conf && \
docker container run --rm -it -v $(pwd):/src -v conf:/dest alpine cp /src/test.cnf /dest/ && \
rm -f test.cnf && \
docker container run --rm -it -v conf:/data alpine cat /data/test.cnfdocker volume create --name VOL_B- than:
docker container run --rm -v VOL_A:/source/folder:ro -v VOL_B:/target/folder \
alpine cp -r /source/folder /targetor without the need for an intermediate directory (cp implementations differ):
docker container run --rm -v VOL_A:/source:ro -v VOL_B:/target debian cp -TR /source /targetdocker volume ls -qf dangling=truedocker volume rm $(docker volume ls -qf dangling=true){: .note} Caution, this also removes named volumes that are currently not mounted by any container!
docker container inspect \
-f '{{ range .Mounts }}{{ .Name }}:{{ .Destination }} {{ end }}' \
CONTAINERdocker-machine ip default
echo 'echo '\''export ENVTEST="Hello Env!"'\'' > /etc/profile.d/custom.sh' | \
sudo tee -a /var/lib/boot2docker/profile > /dev/nulland restart with docker-machine restart default
- create the file
/var/lib/boot2docker/bootsync.shwith a content like:
#!/bin/sh
sudo /bin/su - docker -c 'tce-load -wi nano'- store folders / files in
/var/lib/boot2docker/restore-on-bootand - create the file
/var/lib/boot2docker/bootsync.shwith a content like:
#!/bin/sh
sudo mkdir -p /var/lib/boot2docker/restore-on-boot && \
sudo rsync -a /var/lib/boot2docker/restore-on-boot/ /HEALTHCHECK --interval=1m --timeout=3s --retries=5 \
CMD curl -f <http://localhost/> || exit 1
- see also: HEALTHCHECK
- create the file
/etc/logrotate.d/dockerand insert:
/var/lib/docker/containers/*/*.log {
daily
rotate 14
compress
delaycompress
missingok
copytruncate
}
- check
/etc/cron.daily/logrotateand/etc/crontabfor general logrotate configuration.
{: .note} This example will keep all container logs for 14 days.
printf "\nPulling registry image ...\n" && \
docker image pull registry ; \
printf "\nPreparing registry-cert volume ...\n" && \
docker volume create --name=registry-cert && \
cd /tmp && \
openssl genrsa -out registry.key 4096 && \
openssl req -new -nodes -sha256 -subj '/CN=localhost' -key /tmp/registry.key -out /tmp/registry.csr && \
openssl x509 -req -days 3650 -signkey /tmp/registry.key -in /tmp/registry.csr -out /tmp/registry.pem && \
docker container run --rm -it -v /tmp:/from -v registry-cert:/to --entrypoint sh registry \
-c 'cp /from/registry.key /to && cp /from/registry.pem /to' && \
printf "\nLetting docker client trust certificate ...\n" && \
if [ -d /var/lib/boot2docker ] ;
then
sudo mkdir -p /var/lib/boot2docker/certs && \
sudo cp /tmp/registry.pem /var/lib/boot2docker/certs
else
sudo mkdir -p /etc/docker/certs.d/localhost && \
sudo cp /tmp/registry.pem /etc/docker/certs.d/localhost
fi && \
printf "\nPreparing registry-auth volume (please change 'reg_user' and 'reg_password') ...\n" && \
docker volume create --name=registry-auth && \
docker container run --rm --entrypoint /bin/sh -v registry-auth:/auth registry \
-c 'htpasswd -Bbn reg_user reg_password > /auth/htpasswd' && \
printf "\nPreparing registry-data volume ...\n" && \
docker volume create --name=registry-data && \
printf "\nRunning registry container ...\n" && \
docker container run --name registry -h registry -d \
-v registry-data:/var/lib/registry \
-v registry-auth:/auth:ro \
-v registry-cert:/certs:ro \
--restart=always \
-p 5000:5000 \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.pem \
-e REGISTRY_AUTH=htpasswd \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_STORAGE_DELETE_ENABLED=true \
registry- this script is also available at http://docker.jens-piegsa.com/examples/setup-registry.sh
docker image pull alpine:latest && \
docker login -u reg_user -p reg_password localhost:5000 && \
docker image tag alpine:latest localhost:5000/alpine:private && \
docker image rm alpine:latest && \
docker image push localhost:5000/alpine:private && \
docker image rm -f localhost:5000/alpine:private && \
docker image pull localhost:5000/alpine:private && \
docker logout localhost:5000 && \
docker image ls | grep alpine && \
printf "Deleting image from registry ...\n" && \
curl -X DELETE -u reg_user:reg_password --insecure \
https://localhost:5000/v2/alpine/manifests/$(docker image ls --digests | grep localhost:5000/alpine | awk '{print $3}')docker container rm -f registry && \
docker volume rm registry-data registry-cert registry-auth- advanced authentication: Docker Registry 2 authentication server
- developer notes about deleting images from the registry
-
make a directory called
ciin your home directory on your host system and change into it -
create a file named
docker-compose.ymlwith the following content:
version: "2"
services:
jenkins:
image: jenkins
ports:
- "8082:8082"
- "50000:50000"
restart: always
env_file: .env
environment:
- "JAVA_OPTS=-Dmail.smtp.starttls.enable=true -Dorg.apache.commons.jelly.tags.fmt.timeZone=Europe/Berlin"
- "JENKINS_OPTS=--httpPort=8082"
volumes:
- jenkins_home:/var/jenkins_home
nexus:
image: sonatype/nexus3
ports:
- "8081:8081"
restart: always
env_file: .env
volumes:
- nexus-data:/nexus-data
sonarqube:
image: sonarqube
ports:
- "9000:9000"
restart: always
env_file:
- .env
- sonarqube.env
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://postgres:5432/sonar
- SONARQUBE_JDBC_USERNAME=sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
links:
- postgres
postgres:
image: postgres
ports:
- "5432:5432"
restart: always
env_file:
- .env
- sonarqube.env
environment:
- POSTGRES_USER=sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
volumes:
jenkins_home:
nexus-data:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:- create a second file named
.envthat defines a timezone:
TZ=Europe/Berlin
- create a third file named
sonarqube.envthat holds the database passwords:
SONARQUBE_JDBC_PASSWORD=sonar
POSTGRES_PASSWORD=sonar
- startup all containers:
docker-compose up -d
-
watch the logs, type
docker-compose logsordocker logs -f ci_jenkins_1 -
access the web applications:
- Jenkins on port 8082
- Sonatype Nexus on port 8081 and
- SonarQube on port 9000
- to remove the tool stack (incl. data), use:
docker-compose down -v
docker execis your friend in development, but should be avoided in a production setup
- use named volumes to simplify maintenance by separating persistent data from the container and communicating the structure of a project in a more transparent manner
- always keep environment configuration and secrets out of deployments and images, for example by using environment variables (
-e,--env-file) - always set the
USERstatement, otherwise the container will run asrootuser by default, which maps to therootuser of the host machine - use
ENTRYPOINTandCMDdirectives together to make container usage more convenient - coalesce consecutive
RUNdirectives with&&to reduce the costs of a build and to avoid caching of instructions likeapt-get update - to reduce the size of an image, remove temporary resources in the same
RUNstatement that produces them (otherwise they are still present in an intermediate layer) - use
EXPOSEto document all needed ports - introduce an additional build Dockerfile for your app, if you have a large set of compile-time dependencies (build container pattern)
- Mouat, A. (2015). Using Docker: Developing and Deploying Software with Containers. O'Reilly Media. (German Edition: Docker. Software entwickeln und deployen mit Containern. dpunkt.verlag)
- Turnbull, J. (2016). The Docker Book. Containerization is the new Virtualization.
- Gupta, A. (2016). Docker Container Anti Patterns.
- Piegsa, J. (2016). Dockerbank 2 Workshop. Szenarien des Routinebetriebs. (German Slides)
- Official Docker Documentation
- StackOverflow Documentation
- Awesome Docker
- Docker Labs
- Docker Introduction
- play-with-docker.com
{: .js-toc-ignore }
Feel free to fork this project, send me pull requests, and issues through the project's GitHub page.