But What Is Docker?

Xavi Soler

@xavi_xsb

Containers!

More than 10 years old

technology (in Linux)

 

Previously: BSD Jails, Solaris Zones

Provides isolation

to applications

 

Multiple processes

with conflicting dependencies can run in the same host

Simplifies

application deployment

 

Shipping apps

through the network

in seconds

How does it work?

 

cgroups

namespaces

unionfs

Developer friendly

 

Not like other

container technologies

Programmed in Go

 

Open sourced by dotCloud (now Docker Inc.)

 

2 years ago

What makes Docker special?

It solves problems beyond process isolation and enables interesting workflows

Container creator

doesn't care about what's outside

the container or how to ship it

 

Container operator

doesn't have to care about what's inside

 

Any app can run anywhere.

Solves the "matrix from hell"

Solves the

dev/test/prod parity

 

Developers can run

production-like environments

in their laptops

Artifact

builder and shipper

 

for continuous delivery

Runs anything

that belongs to userland

 

For example, Debian or Busybox based containers in any Linux host

Application dependencies

inside app container

instead of host system

 

Requires less configuration management tools

Simplifies

infrastructure immutability

 

All changes are done

replacing containers

OK but

what is Docker?

  1. Container Runtime
  2. Build System
  3. Storage and Transport Mechanisms
  4. Container Image Manager
  5. Layered Image Format
  6. API for containers

1. Container Runtime

$ docker run
$ docker exec
$ docker stop
$ docker restart
$ docker pause
$ docker logs
$ docker kill
$ docker ps

Run immutable environments

for processes

 

Changes in disk are ephemeral

 

Even by

simultanious executions

Container with attached terminal

$ docker run -t

 

With interactive terminal

$ docker run -it

 

Detach the process and run in background

$ docker run -d

 

Inject processes in a running container

(no need for SSH)

$ docker exec -it angry_stallman /bin/bash

Docker can be used as an
Init System for anything

 

$ docker run -d restart=always myscript

 

This will ensure your container

is running in detached mode

after system boot

Networking, in one slide!

 

Port mapping

$ docker run -d -P xavisb/myapp

$ docker run -d -p 8080:80 xavisb/myapp

 

Docker Linking

$ docker run -d --name=db xavisb/pgsql

$ docker run -d --link db:db xavisb/backend

Inject Environment Variables

 

$ docker run -e PASSWD=12345 xavisb/myapp

 

Want Persistence?

Mount Volumes!

 

$ docker run -d -v /path:/path xavisb/myapp

2. Build System

$ ls
Dockerfile myapp.go README.md

$ docker build -t myapp .

Dockerfile ⇢ Image

 

The same Dockerfile

will always generate

the same image

in repeated builds

 

enabling reproducibility

of container image creation

Image Inheritance

On-Build Triggers

FROM xavisb/my-base-image
RUN apt-get -y install runtimedependencies
COPY mywebserver /mywebserver
CMD ./mywebserver
FROM python:3-onbuild
CMD ["python", "./myapp.py"]

Notice that having:

 

  • a Container Runtime

  • a Build System

  • the ability easily distribute Dockerfiles

  • Docker Compose

 

Means that Docker can be used as an Environment Generator for Development!

3. Storage & Transport

$ docker pull
$ docker push

The Docker Registry

(could be private or public)

 

Stores images than can be pushed or pulled

and then run as containers

 

Hint: docker run = docker pull + docker run

(pull is implicit if image not found locally)

Confusing?

 

  • Registry: collection of repositories

  • Repository: collection of images

  • Image: physical binary file

  • Container: running isolated process

 

your-registry.com/yourapp:v2.0

registry/repository:image

4. Image Manager

$ docker images
$ docker search
$ docker tag
$ docker rmi
$ docker export

List images in your system

$ docker images

 

Search for images in a Docker Registry

$ docker search debian

 

Remove images

$ docker rmi xavisb/myapp:latest

Tag images for versioning
$ docker tag xavisb/app:latest xavisb/app:2.0

 

Publish a specific version
$ docker push xavisb/myapp:2.0

 

Raw storage resides in
/var/lib/docker/

Notice that having

 

  • a Build System

  • a Storage and Transport Mechanisms

  • the ability to version images

 

means that

Docker is...

a fucking

Package Manager

for

Containers

Remember there is no magic

it's simply a filesystem

 

Export a container's filesystem

$ docker export -o container.tar <containerid>

 

See what's inside

$ tar tvf container.tar | less

5. Layered Images

$ docker commit
$ docker diff
$ docker history

Docker Containers

are made of layered filesystems

thanks to UnionFS

(AUFS, DeviceMapper, overlayfs, btrfs, ZFS)

 

A stack of read-only filesystems

with a read-write layer on top of it.

All of this is transparently provided

as a read-write filesystem

(copy-on-write)

Every instruction in a Dockerfile

creates a new layer on top of the previous one

 

A change in one instruction makes

Docker build start from that point

 

Same for push and pull

 

This makes build, publish and deploy

processes really fast

History can show you

how and when an image was created

$ docker history ubuntu

 

Diff can compare changes

since previous layer

$ docker diff <container_id>

 

Don't do this at home

$ docker commit <container_id>

6. API for containers

$ docker inspect <container_name>
[{
    "AppArmorProfile": "",
    "Args": [],
    "Config": {
        "AttachStderr": true,
        "AttachStdin": true,
        "AttachStdout": true,
        "Cmd": [
            "bash"
        ],
        "CpuShares": 0,
        "Cpuset": "",
        "Domainname": "",
        "Entrypoint": null,
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "ExposedPorts": null,
        "Hostname": "a27fa5f20edd",
        "Image": "ubuntu",
        "Labels": {},
        "MacAddress": "",
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkDisabled": false,
        "OnBuild": null,
        "OpenStdin": true,
        "PortSpecs": null,
        "StdinOnce": true,
        "Tty": true,
        "User": "",
        "Volumes": null,
        "WorkingDir": ""
    },
    "Created": "2015-05-18T12:36:49.800975939Z",
    "Driver": "devicemapper",
    "ExecDriver": "native-0.2",
    "ExecIDs": null,
    "HostConfig": {
        "Binds": null,
        "CapAdd": null,
        "CapDrop": null,
        "CgroupParent": "",
        "ContainerIDFile": "",
        "CpuShares": 0,
        "CpusetCpus": "",
        "Devices": [],
        "Dns": null,
        "DnsSearch": null,
        "ExtraHosts": null,
        "IpcMode": "",
        "Links": null,
        "LogConfig": {
            "Config": null,
            "Type": "json-file"
        },
        "LxcConf": [],
        "Memory": 0,
        "MemorySwap": 0,
        "NetworkMode": "bridge",
        "PidMode": "",
        "PortBindings": {},
        "Privileged": false,
        "PublishAllPorts": false,
        "ReadonlyRootfs": false,
        "RestartPolicy": {
            "MaximumRetryCount": 0,
            "Name": "no"
        },
        "SecurityOpt": null,
        "Ulimits": null,
        "VolumesFrom": null
    },
    "HostnamePath": "/var/lib/docker/containers/a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5/hostname",
    "HostsPath": "/var/lib/docker/containers/a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5/hosts",
    "Id": "a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5",
    "Image": "d0955f21bf24f5bfffd32d2d0bb669d0564701c271bc3dfc64cfc5adfdec2d07",
    "LogPath": "/var/lib/docker/containers/a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5/a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5-json.log",
    "MountLabel": "",
    "Name": "/angry_rosalind",
    "NetworkSettings": {
        "Bridge": "docker0",
        "Gateway": "172.17.42.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "LinkLocalIPv6Address": "fe80::42:acff:fe11:2",
        "LinkLocalIPv6PrefixLen": 64,
        "MacAddress": "02:42:ac:11:00:02",
        "PortMapping": null,
        "Ports": {}
    },
    "Path": "bash",
    "ProcessLabel": "",
    "ResolvConfPath": "/var/lib/docker/containers/a27fa5f20edddaa96aeb1a0c82b048aa71489435996a67bea9c0b9754600f7b5/resolv.conf",
    "RestartCount": 0,
    "State": {
        "Dead": false,
        "Error": "",
        "ExitCode": 0,
        "FinishedAt": "0001-01-01T00:00:00Z",
        "OOMKilled": false,
        "Paused": false,
        "Pid": 14763,
        "Restarting": false,
        "Running": true,
        "StartedAt": "2015-05-18T12:36:50.445521305Z"
    },
    "Volumes": {},
    "VolumesRW": {}
}
]

Everything in Docker is made

through an HTTP API

unix:///var/run/docker.sock

 

The Docker client (CLI)

is a consumer of that API

$ docker version
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): 7c8fca2
OS/Arch (client): linux/amd64
Server version: 1.6.2
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): 7c8fca2
OS/Arch (server): linux/amd64

Client and Server

don't need to run

in the same host

 

If you use boot2docker

server runs in Linux VM

and client runs in OSX Host

QUESTIONS?

Made with Slides.com