This document discusses Docker concepts like images vs containers, base images, Dockerfiles, volumes, and ways of building Docker images. It also covers topics like configuration, discovery, routing, and other Docker tools. Specifically, it explains that images are blueprints for containers, containers are instances of images that are writeable, and images are not after creation. It also discusses choosing a base image, tags/versions, and dissects example Dockerfiles.
4. Image vs container
• an image is the blueprint for the container
• a container is an instance of the image
• the container is writeable, while an image is not
(after creation)
• the container state can be committed to form an
image
6. Choosing a base image
• They come in all sizes, for specialised or general
purposes.
• Majority based on some version of Ubuntu, but
many are also small (of size in MB) with a limited
toolset.
7. Choosing a base image
This is one of the questions dividing the community
into two camps:
Should my container run one process, or many?
my process as PID 1
vs
using an init process?
9. Tags / Versions
• Use some time to think through Docker tagging
• Tag is normally a version, but don’t need to be
• Special tag “latest” appended if no tag specified
• Metadata is a new feature - might change the scenarios
where tags was used earlier. Have not looked into it yet.
11. Dissecting a Dockerfile
FROM phusion/baseimage:0.9.16
# Set correct environment variables.
ENV HOME /root
# Regenerate SSH host keys.
# You may also comment out this instruction; the
# init system will auto-generate one during boot.
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
# ...put your own build instructions here...
#RUN apt-get update && apt-get -y upgrade
# Clean up APT when done.
#RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
12. Dissecting a Dockerfile
FROM vimond.artifactoryonline.com/vimond-base
# automatically accept oracle license
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true
| /usr/bin/debconf-set-selections
RUN add-apt-repository ppa:webupd8team/java
&& apt-get update
&& apt-get -y upgrade
&& apt-get -y install
oracle-java8-set-default
oracle-java8-unlimited-jce-policy
oracle-java8-installer
libsnappy-java
python-software-properties
# Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
13. Dissecting a Dockerfile
# vim:set ft=dockerfile:
FROM vimond.artifactoryonline.com/vimond-base-java-8
MAINTAINER Olve Sæther Hansen <olve@vimond.com>
# Set correct environment variables.
ENV HOME /root
# Regenerate SSH host keys. baseimage-docker does not contain any, so you
# have to do that yourself. You may also comment out this instruction; the
# init system will auto-generate one during boot.
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]
# automatically accept oracle license
#RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true
# | /usr/bin/debconf-set-selections
RUN apt-get update
&& apt-get -y upgrade
&& apt-get -y install
python-pip
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN pip install cqlsh
#Swaps (ubuntu) dash with bash for easier sourceing
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
COPY docker-service.sh /tmp/docker-service.sh
COPY docker-service-startup-command.sh /etc/my_init.d/docker-service-startup-command.sh
RUN chmod a+x /etc/my_init.d/docker-service-startup-command.sh
ONBUILD COPY docker/docker-config.yml docker/docker.properties build/libs/*.jar target/*.jar /tmp/
ONBUILD RUN rm -fv /tmp/*tests*.jar
#Notes on variables below. $UPPER_CASE means variables to be evaluated at runtime, all file names in
#/etc/container_environment will be a variable name with the file content as value.
#Variables with $lower_case means the var should used only in the Dockerfile image build phase.
#This is for keeping the confusion at bay.
ONBUILD RUN source /tmp/docker.properties
&& useradd -ms /bin/bash -d /opt/$service_name -G docker_env $service_name
&& mkdir /var/log/${service_name}
&& mkdir /etc/service/${service_name}
&& mv /tmp/docker-service.sh /etc/service/$service_name/run
&& echo $service_name >> /etc/container_environment/SERVICE_NAME
[snip]
15. Ways of building images
• Image from direct container changes
• Dynamic Dockerfile
• Static Dockerfile
16. Things to think about
• size of image (.dockerignore)
• compile inside or outside of image?
• what to do about secrets?
• what do do about dependencies
• what to do about access to dependencies (repos)
• (sure I forgot something - anyone?)
19. hub.docker.com
• the GitHub for Docker
• IMO best for public images, as rights
management and building can be cumbersome
for private repositories
20. hub.<yoursite>.com
• The registry is open source, so it is possible to
run it locally
• Have not tried this - might be a sound solution
21. <yoursite>.artifactoryonline.com
• We went for this solution, as we already store our
jar-files, npm builds and gems in Artifactory.
• Some other nice features for image promotion
• Probable other solutions, both onsite or as a
service in this space
23. Mounted Volumes
• Mount files or folders from host to the container in RO or
RW mode.
• Useful for
• static data,
• complex configurations
• getting logs out of the container
• any dynamic data created in container that you want to
keep
24. Data Volume Container
• Data volumes can be created from scratch or from
a docker container which has a volume.
• use “—volume-from” command when starting/
creating other container
• useful for dynamic data that can be versioned,
shared and used in different environments
(e.g. databases)
25. What is going on inside a
container
• Can be a bit cumbersome, but possible to
introspect in many ways.
• top (processes are exposed to host)
• ssh (if ssh server enabled- re multiple processes)
• docker exec -t -i <container id> bash -l
• docker inspect <container id>
27. Docker Compose
• previously known as fig
• Tool for setting up several containers linked
together.
• Handled by a single configuration
• We use it to set up infrastructure and perform
integration tests
30. Configuration
• use production optimised defaults
• use a sane convention and override when needed
• make configuration expressible via system
variables when possible
(meaning no lists, maps etc)
32. Discovery
• Keep service discovery out of the service
• Keep service discovery out of the image containing
the service
• Use Docker events and have a dedicated
discovery agent running and reporting
34. Routing
• We have now many services/containers running, each on
a random port on different machines.
• How do we route traffic to and from?
• Docker Compose can help (also in prod systems)
• We decided to write HAProxy configs on the fly based on
Docker events (via a service discovery system - Consul
and Registrator)
• Consul-template reacts to events in consul, and rewrites
configuration files
35. HAProxy service routing
• Typically two HAProxy servers with identical configuration
• One front-end on port 80 that selects backend based on DNS
• One backend for each service
• Many load balanced servers (potentially) for each backend
• Service outage will rewrite configuration file and restart
HAProxy
• Service additions will rewrite configuration file and restart
HAProxy
36. Other interesting Docker
tools and notes
• Docker Machine
• Docker Swarm
• ECS from Amazon
• https://github.com/gliderlabs/logspout
• https://github.com/GoogleCloudPlatform/kubernetes
• Many others, but difficult to separate hype from
promising projects.