Docker¶
(Update: for most of my uses, I currently prefer LXC and LXD, and so haven’t used Docker in quite some time.)
Right now, this is just notes and a cheatsheet as I learn more about Docker. Again, most of this stuff can be found elsewhere, and I tried to list in the Resources section all of the places from which I took content and ideas.
some of my example dockerfiles¶
usage¶
here’s a more thorough cheatsheet
images | description |
---|---|
images |
list local images |
run -ti --name <name> <image> <command> |
run image (i.e. create container with optional name) with command interactively (-i) and allocate a pseudo tty (-t) |
build -t namespace/repo:tag . |
use Dockerfile in current directory to build image named tagname |
rmi -f <image> |
delete a local image |
tag <hash> namespace/repo:tag |
tag an image for upload to docker hub under namespace (hub account) |
login |
login to docker hub |
push <user>/<imagename> |
push image to docker hub |
commit |
save changes made in a container |
containers | description |
---|---|
run -ti --name <name> <image> <command> |
run image (i.e. create container with optional name) with command interactively (-i) and allocate a pseudo tty (-t) |
start -ai <container> |
start an existing container (e.g. previously created from image with ‘run’ command) |
ps -a |
show all containers, running or stopped |
rm <container> |
delete a container |
run --rm |
remove the container on exit |
data volumes | description |
---|---|
run -ti -v /mount_pt <image> <command> |
create container with a persistent, unnamed volume at mountpt |
|
create container with a persistent volume named name |
run -ti -v /abs/host/path:/mount_pt
<image> <command> |
create container with a host path mounted at mountpt |
run -ti --volumes-from <containername>
<image> <command> |
create container and attach volumes from container-name |
utilities¶
a shell function I found on stackoverflow to help with cleanup:
dcleanup() {
docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2>/dev/null
docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null
}
probably can now use docker system prune -a
for this
advice and best practices¶
ENTRYPOINT vs. CMD¶
ENTRYPOINT vs. CMD In summary, for a container called ‘demo’:
ENTRYPOINT | CMD | |
---|---|---|
overriding default command | docker run --entrypoint hostname demo |
docker run demo hostname |
setting up default flags | holds the hard-coded command and flags | flags get overwritten by
docker run demo flags
command line |
Always use the “exec form” instead of the “shell form” for both CMD and
ENTRYPOINT. E.g. CMD ["executable","param1","param2"]
so that:
- our command gets PID 1 and we can send posix signals to it, etc. With the shell form, a shell gets PID 1 to execute the command, and won’t forward signals.
- combining ENTRYPOINT and CMD together works as expected
Users and mapping¶
Docker and locales¶
Best practices¶
best practices for writing Dockerfiles
Docker usage; a philosophy 1. One process per container 2. Keep image files short (strictly less than 127 layers) 3. containers vs. images vs. dockerfiles
containers: how you run your application
images: how you store your application
dockerfile: tells docker how to create the container for your application
- lives beside your source code
- “glorified bash script with a few extra commands”
- Use docker compose for realistic development stacks
Docker and persistent data¶
https://docs.docker.com/engine/tutorials/dockervolumes/ This is the standard Docker documentation about data volumes. At the time of this writing, it is a little bit sparse and outdated from best practices.
https://boxboat.com/2016/06/18/docker-data-containers-and-named-volumes/ This is an excellent tutorial with some more background about how data volumes relate to the Docker filesystem, and which to choose when.
http://crosbymichael.com/advanced-docker-volumes.html Another good article with some depth about volumes
https://github.com/docker/docker/issues/17798#issuecomment-154815207 Some comments about deprecating the use of data containers
Now that we’ve read/reviewed the links above, we see that there are a few options to consider when working with persistent data and Docker. To summarize:
data volume container: deprecated in favor of named volumes - not going to discuss this one since I don’t use it.data volume: these have several modes of usage that should cover all situations now
- “bare” data volume - unlabeled, usually only used to persist data in a single container. labelled with a hash and lives in (/var/lib/docker/volumes).
- named data volume - label chosen at volume creation time. This is like a bare volume, but easier to manage. another way to look at it: a host directory volume, but managed by the docker tools instead of the host user, lives in a location in the host filesystem that is decided by Docker, etc..
- host directory data volume - labeled by an existing directory/file in the host filesystem. this directory/file gets mounted inside the container when it is created/started.
There are two ways to create a data volume: either by itself or at the same time as container creation.
stand-alone volume creation¶
Use docker volume create
to a bare volume:
$ docker volume create
6a7b1bc554a43534a34659af12b0ec4e088a595c5fc05e716c31ce91380ee615
$ docker volume ls
DRIVER VOLUME NAME
local b441fb44bfe8ee3b1de4e2bf157b2560c3ccae5096ab734d972902e6dc2bac73
or add a named volume:
$ docker volume create --name test-volume
test-volume
$ docker volume ls
DRIVER VOLUME NAME
local b441fb44bfe8ee3b1de4e2bf157b2560c3ccae5096ab734d972902e6dc2bac73
local test-volume
volume creation at container creation time¶
To create a bare volume at container creation time and mount it inside the
container at /data_dir
:
$ docker run -t -i -v /data_dir some-repo/some-container:tag /bin/bash
[exit container]
$ docker volume ls
DRIVER VOLUME NAME
local b288739dff62212d67c5b7dc4bc5dd2f2b40685fd3b6731994daf2466aa86b06
local b441fb44bfe8ee3b1de4e2bf157b2560c3ccae5096ab734d972902e6dc2bac73
local test-vol
or a named volume (named ‘persist’, mounted at /data_dir
) using the same
method:
$ docker run -t -i -v persist:/data_dir grahamican/centos-dev:gcc /bin/bash
[exit container]
$ docker volume ls
DRIVER VOLUME NAME
local b288739dff62212d67c5b7dc4bc5dd2f2b40685fd3b6731994daf2466aa86b06
local b441fb44bfe8ee3b1de4e2bf157b2560c3ccae5096ab734d972902e6dc2bac73
local persist
local test-vol
mount a host directory inside a container¶
- ::
- $ docker run -t -i -v /Users/graham/develop/gcc-6.2.0:/gcc_source grahamican/centos-dev:gcc /bin/bash [in a different shell] $ docker volume ls DRIVER VOLUME NAME local b288739dff62212d67c5b7dc4bc5dd2f2b40685fd3b6731994daf2466aa86b06 local b441fb44bfe8ee3b1de4e2bf157b2560c3ccae5096ab734d972902e6dc2bac73 local persist local test-vol
notice that the host directory volumes don’t show up with docker volume
commands, because docker isn’t helping to manage them (e.g. you can’t docker rm
a host directory)
So now we can deduce some rules about creating/naming volumes (as given on the
Docker volume documentation page) when using
docker run -v volume_name:/path/to/mount
…:
if
volume_name
is not an absolute path, use a named volume1. if the name already exists, mount it in the new container (
docker run --volumes-from container-name
can be used as a shortcut here) 2. if it doesn’t exist, create it and mount itif
volume_name
is an absolute path, mount the host directory/file at that path
Finally, these things can be done in a Dockerfile with the VOLUME command. Note that volumes cannot be mounted into a pre-existing container. (One must commit the changes to the existing container to create a new image, then create a new container with the volume mount(s)).
installing docker on ubuntu 18.04¶
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04
installing docker on rhel7.4 and centos¶
yum install docker-latest
usermod -aG docker bgl
systemctl start docker-latest
systemctl enable docker-latest
increase available size
- vim /etc/sysconfig/docker-latest
- add
-g /path/to/runtime/storage
- and
--storage-opt dm.basesize=50G
toOPTIONS=
installing docker on gentoo¶
The gentoo wiki page on docker is quite good.
Problems / Solutions¶
- if there is no network connection during build/run (I’ve seen this on ion
when trying to e.g.
apt update
), can usedocker build --network host
anddocker run --network host
- can use tmpfs inside a container at a mount point with
docker run --tmpfs /tmp:rw,exec
Resources¶
https://github.com/wsargent/docker-cheat-sheet a nice general cheatsheet
https://youtu.be/Q5POuMHxW-0 dotCloud/Docker founder Solomon Hykes explains motivation and reasoning behind Docker
https://youtu.be/q1qEYM_SESI some overview and rules of thumb
Docker and the PID 1 zombie reaping problem
Ensuing discussion on reddit a little bit about the “one process per container” rule of thumb
Todo¶
best practices and motivation
architecture (e.g. unionfs, etc.)
nvidia docker and gpu development
multiple container dockerfile example: chat = bitlbee + znc + weechat
use case walkthroughs
security and other considerations
- e.g. http://link.springer.com/chapter/10.1007/978-3-319-46079-6_48 and others
--cap-add sys_ptrace
,--privileged
and friends to get debugging to work inside a containershifter and nextplatform article, and singularity and an admin-magazine article, etc.