The kernel features that enabled Docker are:
-
Namespaces allow execution isolation
-
cgroups (control groups) allow resource limit control
-
Capabilities allow permission management (deny all by default)
Docker needs an execution driver. The execution driver is the interface with the kernel features Docker requires, that is namespaces, cgroups, capabilities. LXC was the initial execution driver but now libcontainer is used, that is owned and controlled by Docker and may be installed in Windows as well. The Docker engine that consisted of a client and a daemon.
$ apt-get install -y docker.io $ service docker.io status
$ curl https://get.docker.com | sh
$ docker -v (1) $ docker version (2) $ docker info (3) $ docker run hello-world (4)
-
the docker client asking the docker daemon for the version
-
more detail
-
information on the docker installation, images, etc
-
runs a sample container
$ docker run -it ubuntu /bin/bash
-
run
: starts a new container -
-it
: make it interactive, assign a tty -
ubuntu
: base it on the ubuntu image -
/bin/bash
: inside the container launch the bash process
Caution
|
Issuing exit , or entering ctrl+d will terminate the container.
|
docker run --name $given_container_name -p 3306:3306 -d image_name
-
--name $given_container_name
: name the container -
-d
: detached -
-p 3306:3306
: map network port from host to container
$ docker run ubuntu /bin/bash -c "echo 'cool content' > /tmp/cool-file"
$ docker exec -it $container_name /bin/bash (1) $ docker exec -d $container_name touch /tmp/log (1)
-
Executes interactively a shell in a running container with name
$image_name
-
Creates a file, detached, in a running container
In the previous example the container was started using the local socket. To launch a container from a network socket, the docker daemon must be stopped and restarted to listen on a network port.
$ service docker stop $ docker -H 192.168.1.3:55555 -d &
-
-H host:port
: The host and port to start docker -
-d
: daemonize -
&
: Get the terminal back
$ netstat -t4lp (1) $ docker info (2) $ export DOCKER_HOST="tcp://192.168.1.3:55555" (3) $ docker info (4)
-
check that docker listens
-
returns an error, since by default docker used the local socket
-
set the environment variable
-
now it works! (check firewalls if it does not)
$ docker ps (1) $ docker ps -a (2) $ ls -l /var/lib/docker/aufs/diff (3) $ ls -l /var/lib/docker/aufs/diff/$hash (4) $ docker start $hash (5) $ docker attach $hash (6) $ docker pull $image_name (7) $ docker images $image_name (8) $ docker stop $hash (9)
-
show running docker containers
-
all docker containers on this machine
-
the images
-
the directory structure of
$hash
-
starts docker container with id
$hash
-
attach on process with PID1 on the running container with id
$hash
-
pulls
$image_name
from docker hub (latest version) -
shows all images for
$image_name
(all versions) -
stops running container
$hash
Tip
|
[ctrl] + [p] + [q] exits (detaches from) a container without killing it. Use docker attach $hash to reattach.
|
A Registry (hub.docker.com) contains many Repositories (fedora, ubuntu, redis, etc).
Images are stacked from more elementary images. For example:
-
Base Image
-
Application (e.g redis)
-
Patches
The top layer overrides the previous ones. This is accomplished through union mounts (how to mount multiple file systems on-top of each other). All these layers are mounted as read-only with a top layer as read/write. Only the very top level is writable. The bottom layer is bootfs, that is short lived and no one will ever have to deal with it.
$ docker images
-
All locally stored images
The default docker repository is dockerhub. Nevertheless, one might want to use other repositories, and typically not HTTPS ones e.g. in the case when a valid certificate is not available and you want to proxy DockerHub through Nexus.
Provided that one has already configured Nexus accordingly, add the following on the client machines:
/etc/docker/daemon.json
{
"insecure-registries": [
"my-nexus:8082",
"my-nexus:8083"
],
"disable-legacy-registry": true
}
$ sudo systemctl restart docker
$ docker login -u admin -p admin123 my-nexus:8082 $ docker login -u admin -p admin123 my-nexus:8083
$ docker run -it my-nexus:8082/ubuntu /bin/bash
The procedure in high level steps is:
-
Save the container to a tar file
-
Export it
-
Import it
$ docker commit $hash alias (1) $ docker images (2) $ docker history alias (3) $ docker save -o /tmp/export.tar alias (4) $ docker load -i /tmp/export.tar (5) $ docker images (6)
-
creates a docker images from $hash
-
the previously committed image is displayed
-
shows the commands that created the image
-
exports alias image as tar
-
imports it, in another instance
-
shows up!
$ docker run -d ubuntu /bin/bash -c "ping 8.8.8.8 -c 30" (1) $ docker top $hash (2) $ docker run ubuntu:version (3)
-
ping host from an ubuntu based container
-
lets us see top running processes into a container
-
be explicit!
-
-i
: interactive -
-t
: assign a tty -
-d
: detached -
--rm
: remove container when it exits -
--cpu-shares
: how much CPU (1024 being 100%) -
--memory
: how much memory to use -
--restart (no|on-failure|unless-stopped|always)
: restart container on daemon restart according to policy
$ docker inspect $hash (1) $ docker ps -l (2) $ docker rm $hash (3) $ docker rm -f $hash (4) $ docker log $hash (5)
-
get detailed information on the container
-
shows the last container to have run
-
remove a stopped container
-
remove a running container
-
what happens in the container (add -f to follow)
docker attach
, attaches to PID1 of a running container. If PID1 is not a shell, then attaching wont be of much use. In that case:,
$ docker inspect $hash | grep Pid (1) $ nsenter -m -u -n -p -i -t pid /bin/bash (2) $ docker-enter $hash (3) $ docker exec -it $hash /bin/bash (4)
-
find the PID of the running container
-
logs into the container
-
same thing as above
-
same thing as above
Note
|
Logging out of this container will not stop it! |
It is possible to set up docker container networks.
Start containers with the --network="host"
option. In that case, -p
and -P
options do not take effect, but the container will be able to access all
localhost endpoints, even ones that are started as docker containers.
-
To store mutable container data externally
-
To share data between host and containers
-
To share data between containers
$ docker run -v $from_host_dir:$to_guest_dir $image_name
$ docker run -it -v /tmp ubuntu /bin/bash
$ docker volume create --name vol $ docker run -it -v vol:/data ubuntu /bin/bash
$ docker create -v /tmp --name datacontainer ubuntu (1) $ docker run -it --volumes-from datacontainer ubuntu /bin/bash (2)
-
Creates a volume based on
ubuntu
, nameddatacontainer
to be mounted on/tmp
to containers that will want to use it. -
Runs a container that mounts the previously created volume. Now even after destroying the container, data stored on the volume will remain. Volume can only be mounted on the directory declared during volume creation time, that is
/tmp
.
Access to registries require login.
$ docker login docker_registry:port
Login in creates or updates a file in $HOME/.docker/config.json
, that looks like:
{ "auths": { "192.168.56.1:18000": { "auth": "YWRtaW46YWRtaW4xMjM=" } } }
Tip
|
The authentication token is base64 encoded and can be decoded like so, $ echo "token" | base64 -d
|
To logout:
$ docker logout docker_registry:port
A Dockerfile contains simple instructions to create a docker image.
-
Plain text
-
Simple format
-
Instructions to build an image
-
All other subdirectories will be included in the build
$ docker build (1) $ docker build -t mytag:version . (2)
-
builds an image with instructions from the Dockerfile
-
tag and build from local directory
# comment FROM image:version MAINTAINER email RUN runCommand1 # creates a new layer! RUN runCommand2 # creates a new layer! CMD ["echo", "Hello", "World"]
-
RUN
: Executes only during build time -
CMD
: Executes only during run time and can only be one -
EXPOSE
: Exposes a network port -
ENTRYPOINT
: The command to run, cannot be overridden and anything appended from the command line is passed as argument
Tip
|
ENTRYPOINT specifies a command that will always be executed when the container starts. CMD specifies the default arguments that will be fed to the ENTRYPOINT which can be overwritten from command line when docker container runs.
|
$ docker tag $hash repo/$image_name:version (1) $ docker push repo/$image_name:version (2) $ docker rmi $image_name (3) $ docker system prune --volumes (4)
-
tags
$hash
-
pushes
$image_name
to repository -
removes
$image_name
-
remove all stopped containers, all dangling images all unused networks and volumes
$ docker pull wnameless/oracle-xe-11g $ docker run -d -p 1522:22 -p 1521:1521 wnameless/oracle-xe-11g
hostname |
localhost |
port |
1521 |
sid |
xe |
username |
system |
password |
oracle |
Login with SSH (password: admin)
ssh root@localhost -p 1522