Created by Paul Czarkowski / @pczarkowski
Cloud Engineer - BlueBox Cloud
FROM ubuntu:latest
ADD . /home/docker
ADD https://dist.torproject.org/torbrowser/4.0.4/tor-browser-linux64-4.0.4_en-US.tar.xz /home/docker/tor.tar.xz
RUN apt-get update && true
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get install -y firefox
RUN localedef -v -c -i en_US -f UTF-8 en_US.UTF-8 || :
RUN useradd -m -d /home/docker docker
RUN cd /home/docker && tar xJf /home/docker/tor.tar.xz
USER docker
CMD ["/home/docker/tor-browser_en-US/start-tor-browser"]
Optimizing your Dockerfile for build cache hits.
Sort your commands by
Use the image of the application that is consuming it as the base for the volume container.
FROM ubuntu:latest
ADD . /home/docker
ADD https://dist.torproject.org/torbrowser/4.0.4/tor-browser-linux64-4.0.4_en-US.tar.xz /home/docker/tor.tar.xz
RUN apt-get update && true
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get install -y firefox
RUN localedef -v -c -i en_US -f UTF-8 en_US.UTF-8 || :
RUN useradd -m -d /home/docker docker
RUN cd /home/docker && tar xJf /home/docker/tor.tar.xz
USER docker
CMD ["/home/docker/tor-browser_en-US/start-tor-browser"]
"I don't need Config Management now that I have Docker."
You probably shouldn't be trusting docker [yet] for managing long term persistent data.
Persistent data stores and other infrastructure services have to be managed by something.
https://supermarket.chef.io/cookbooks/docker
include_recipe "docker::default"
docker_image 'registry' do
action [:pull]
end
docker_container 'registry' do
detach true
port '5000:5000'
action [:run]
end
node['my_app']['images'].each do |image|
docker_image image do
action [:pull]
end
docker_image image do
repository "#{node['my_app']['registry']}/#{image}"
registry node['my_app']['registry']
action [:tag, :push]
end
end
git "#{Chef::Config[:file_cache_path]}/docker-testcontainerd" do
repository 'git@github.com:bflad/docker-testcontainerd.git'
notifies :build, 'docker_image[tduffield/testcontainerd]', :immediately
end
docker_image 'tduffield/testcontainerd' do
action :pull_if_missing
end
Almost anything that can be done with docker can be done via the docker cookbook.
Puppet and Ansible both have a similar story.
You probably shouldn't...
But if it makes sense in your use case ... go for it.
Consider Chef for Containers if you want to do this, it will help deal with managing services etc.
Run Chef from a volume mount so that it doesn't actually live in your container.
If you're already using a tool like Packer to create images with Config Management, you can probably switch it to build Docker images very easily.
If you're like me and run an OS that's not well supported by ChefDK ... run it in a container.
$ docker run -d -v ~/chef/cookbook:/cookbook --name chefdk spheromak/docker-chefdk sleep 6000000
$ docker exec -ti chefdk bundle install
$ docker exec -ti chefdk rake test
This used to be hard. It's a lot less hard now.
Try your very best not to ever log to a file in the container. Otherwise you will probably face logfile management issues.
Logspout by @progrium
$ docker run -v=/var/run/docker.sock:/tmp/docker.sock \
progrium/logspout \
syslog://logs.papertrailapp.com:55555
But my app doesn't log to stdout/stderr.
It does now!
# /etc/nginx/nginx.conf
worker_processes 1;
daemon off;
user app app;
pid /app/nginx.pid;
error_log /dev/stderr;
access_log /dev/stdout;
...
But seriously I can't configure it to log to /dev/stdout
Logging improvements coming soon!
CAdvisor to the rescue.
sudo docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
Cadvisor natively support Docker and most linux containers based on LXC
There are times when you need to run multiple processes in a container.
Ignore the nay-sayers ... this is OK.
#!/bin/boot
mysqld_safe &
/usr/bin/hhvm --config /etc/hhvm/server.ini --user app -m server &
apache2 -DFOREGROUND
Problems
Docker and the pid 1 zombie reaping problem
I have an application in a container ... but how do I actually configure it ?
This is the simplest use case, if your configuration file is very static just use ADD in your `Dockerfile` to put it in the correct place.
You can also mount it in from your host ( useful if already using CM to write the config file on the host ).
docker run -d -v /my/app/apache2/httpd.conf:/etc/apache2/httpd.conf myapp
It's OK to do this, but be aware of the potential security implications.
#!/bin/bash
PORT=${PORT:-5000}
sed -i "s/xxxPORTxxx/$PORT/" /etc/apache2/httpd.conf
exec apache2 -DFOREGROUND
FROM ubuntu:trusty
RUN \
curl -sSL -o /usr/local/bin/etcdctl \
https://s3-us-west-2.amazonaws.com/opdemand/etcdctl-v0.4.6 \
&& chmod +x /usr/local/bin/etcdctl \
&& curl -sSL -o /usr/local/bin/confd \
https://github.com/kelseyhightower/confd/releases/download/v0.7.1/confd-0.7.1-linux-amd64 \
&& chmod +x /usr/local/bin/confd
#!/bin/bash
BACKEND=${BACKEND:-env}
until confd -onetime -backend=${BACKEND} -confdir=/etc/confd ; do
echo "echo ==> ${APP_NAME}: waiting for confd to write initial templates..."
sleep 1
done
exec apache2 -DFOREGROUND
$ docker run -d -p 8080 \
-e APACHE_PORT=8080 -e APACHE_ROOT=/app/web \
apache /app/bin/boot
Deeper dive into confd during demo / workshop.
docker pull factorish/example
$ docker run -d -e SERVICES_EXAMPLE_TEXT=father \
-p 8080:8080 --name father factorish/example
$ curl localhost:8080 # or IP of boot2docker
$ docker run -d -e SERVICES_EXAMPLE_TEXT=mother \
-p 8081:8080 --name mother factorish/example
$ curl localhost:8080 # or IP of boot2docker
$ docker kill father mother
$ docker rm father mother
$ vagrant up
.....
$ vagrant ssh core-01
$ etcd ctl / --recursive