Docker Basics

Docker is a platform that allows you to build, ship and run applications in a controlled environment called a container. Containers provide isolation from each other and from the underlying infrastructure.

Docker has support for Linux and Windows-based containers. Containers consume less resources than traditional VMs, and processes running in containers actually share the base operating system kernel. Although containers are self-sufficient and contain everything the application needs to run, they aren't portable across platforms or architectures. For instance, Linux x86 containers will not run on Windows machines or Linux ARM machines.

Docker Images and Containers

The primary unit of work under Docker is a running Docker container.

A Docker container is launched from a Docker image, much like a  running process is launched from a program on disk. The Docker image provides the filesystem view for the container, along with metadata about the runtime, like environment variables, volumes, ports exposed, etc.

Docker images are built and shipped as an ordered collection of filesystem layers and are progressively built layer by layer. Docker images can be built  via the Docker CLI and a recipe called a Dockerfile, or by one of the many third-party tools that do the same job. The Docker native build command interprets the Dockerfile line by line. Each interpreted line results in a new filesystem layer or a piece of metadata about the final image.

Here's an example of a Dockerfile:

FROM debian:jessie
MAINTAINER Andras Mitzki <andras.mitzki@balabit.com>

RUN apt-get update -qq && apt-get install -y \
   wget \
   gnupg2

RUN wget -qO - https://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/Debian_8.0/Release.key | apt-key add -

RUN echo 'deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/Debian_8.0 ./' | tee --append /etc/apt/sources.list.d/syslog-ng-obs.list


RUN apt-get update -qq && apt-get install -y \
   syslog-ng
ADD openjdk-libjvm.conf /etc/ld.so.conf.d/openjdk-libjvm.conf

RUN ldconfig

EXPOSE 514/udp

EXPOSE 601/tcp

EXPOSE 6514/tcp

ENTRYPOINT ["/usr/sbin/syslog-ng", "-F"]

 

See https://docs.Docker.com/engine/reference/builder for more information on Dockerfiles.

 

Docker Registry

A Docker registry is a server or service that  acts as a repository for Docker images. The registry stores images as a collection of layers. Layers are identified by their checksum. This allows Docker and the registry to de-duplicate layers. When Docker pushes images to a registry, it only pushes layers that don't already exist on the registry. Similarly, when Docker pulls images from a registry, it only pulls layers that it doesn't already have.

Docker registries can run on-premises or in the cloud. There are commercial as well as free offerings for both. Some registries require authentication and provide access control for operations on the registry.

See the Docker usage summary section on how to authenticate with a Docker registry.  

Running a Container

When Docker launches a container, it first pulls all the filesystem layers that comprise the image to the local filesystem. This image is then mapped as the root of the container filesystem. Docker also allows for the creation of independent volumes that can be attached to multiple containers. You can map volumes from the host machine into the container, ports from the public interface to the container, set environment variables, etc. See the command summary section for an example.

Docker Usage Summary

Most examples here are only illustrative. For complete command syntax and options, refer to the links below each. Commands referring to image:tag, can also optionally be prefixed with server:port/ to point to specific Docker registries rather than the default hub.Docker.com.

Logging into a registry:

Usage: docker login [SERVER]

Full documentation: https://docs.docker.com/engine/reference/commandline/login/

Pull an image from the registry:

$ docker pull alpine:3.5

Full docuemtation: https://docs.docker.com/engine/reference/commandline/pull/

List images on the local machine:

$ docker images

Full documentation: https://docs.docker.com/engine/reference/commandline/images/

Remove a local image:

$ docker rmi alpine:3.5

Full documentation: https://docs.docker.com/engine/reference/commandline/rmi/

Launching a container (example):

$ docker run -it --rm -v /host/path:/some/path/in/container -e TERM=xterm -p 443:8443 --name myalpine alpine:3.5 sleep 600

This command funs the Alpine Linux image tagged as 3.5 in interactive (-i) mode with an allocated pseudoterminal (-t). It maps volume (-v) path /host/path on the base OS to /some/path/in/container inside the container. It passes in  an environment (-e) variable TERM=xterm into the container. It maps (-p) external port 443 to port 8443 in the running container. Finally, it runs "sleep 600" inside the container. The running container is named (--name) "myalpine".

For more information: https://docs.docker.com/engine/reference/run/

List running containers:

$ docker ps

Add option -a to list all containers including stopped ones

Full documentation: https://docs.docker.com/engine/reference/commandline/ps/

Entering or running a command in a running container:

$ docker exec myalpine ps -ef

Runs ps -ef inside a running container named myalpine

Full documentation: https://docs.docker.com/engine/reference/commandline/exec/

 

Stopping a container:

$ docker stop myalpine

Stops the container named myalpine

Full documentation: https://docs.docker.com/engine/reference/commandline/stop/

 

Removing a container:

$ docker rm myalpine

Removes the stopped container named myalpine

Full documentation: https://docs.docker.com/engine/reference/commandline/rm/

Customize Wercker Boxes and Services

Wercker uses Docker containers in the pipeline to provide toolchain boxes and auxiliary services. It might be necessary to customize existing Docker images or create entirely new ones for Wercker boxes or services. The easiest way to do that is with a Dockerfile.

Here's an example that expands the Python container to add Python minifier support. In an empty directory, create a file named Dockerfile that contains this.

 

FROM python

RUN pip install pyminifier

 

This Dockerfile creates a new image from the Python base image. The RUN line adds a new layer that contains the pyminifier package.

To build, tag and push this into the default Docker registry (hub.Docker.com), in the same directory as the Dockerfile, run:

$ docker build -t hubuser/pyminifier:some-tag .


$ docker push hubuser/pyminifier:some-tag

 

In the above example, hubuser is your Docker Hub username. You may need to authenticate before you can push to the registry.

 

You can now use this container image in your pipeline definition as:

build:


   box:

     Id: hubuser/pyminifier

     username: $USERNAME

     password: $PASSWORD

     tag: some-tag

     registry: registry.local

   steps:

     ...