SlideShare ist ein Scribd-Unternehmen logo
1 von 47
Docker feedback
Feedback about Docker first experience at Tribal Nova
2015/01/19
Nicolas DEGARDIN <ndegardin@tribalnova.com>
Overview
• Docker intro
• Docker
• Architecture: nginx multi-projects
• Architecture: nginx single project
• Architecture: nginx single-project test procedure
• Conventions
• Vagrant
• Docker + Vagrant
• Docker + Vagrant provisioner
• Docker + Vagrant provider
• Docker + Vagrant + PHPStorm
• Docker + other tools
• Hints
• Conclusions so far
Docker intro
What is Docker?
A container management tool:
Allows to embed an application and its dependencies in a virtual and portable
container.
Technologies involved:
•cgroups
•LXC (linux container)
•AUFS (Another Unix File System)
At the time of writing this document: Docker 1.4.
Docker intro
What is not Docker?
A virtual machine management tool.
A provisioning tool.
Docker is voluntarily restrained to disallow build parametrizing.
Technics involving generating/altering the build file make no sense: this is not
the point of Docker, and there are better suited tools to serve this purpose.
Docker intro
My first objectives:
•Full development environment quickly set up
•Get rid of the dependencies problems
•Unified configuration between developers/projects
•Reusable containers for other purposes:
–Deployable in other environments than DEV
–Tests/continuous integration
•Configurable containers
•But keeping configuration simple (avoiding too heavy command lines/deep
understanding of these containers)
•Integrate the docker image inside the project
•If possible, no adaptation to our projects configuration
Docker
Installation:
•As a Linux package (lxc-docker)
•With « boot2docker » under Windows and Mac OS
– may not run directly under these environments as it is built upon Linux 2.6
kernel features
– boot2docker is supposed to turn transparent the OS gap
– boot2docker is really lightweight: no package manager. Not meant to be
used as a host VM
•Via a vagrant provisioner…
Docker
Images based upon Dockerfile, aimed at being hierarchical.
No parametrization, no factorization (no includes, no reusable files)
FROM …
ADD…
RUN …
RUN ...
ENTRYPOINT …
CMD …
FROM A
ADD…
RUN ...
ENTRYPOINT …
CMD …
FROM …
RUN ...
FROM A
ADD…
RUN …
RUN ...
CMD …
FROM B
RUN…
RUN ...
A
B
C
D
Docker
Containers can communicate via sockets, file volumes and environment
variables. These communication modes are not bidirectionnal.
first_container:A second_container:A third_container:B
Volumes from
second_container:
the folders from
the second
container are
visible in the first
container
Linked to third
container:
network features
and env variables
that allow socket
communication
Docker
Note about volumes:
•When a volume from a container is mounted into another one, both can read
and write inside at runtime
•A mounted volume can erase another one (or cover it – AUFS)
•If the volume is defined during the build, files inside its directory may
disappear (before or after the volume is defined, different behaviours have
been observed for similar cases)
•Volume files cannot be commited and are not inherited by child images
So the developer should be cautious and avoid too audacious structures. I
observed surprising/strange behaviours when experimenting for some edge
cases. It also seems more secure to declare volumes when running the
container.
Architecture
Here comes my feedback from different container architectures
experimentations.
I represent:
•containers by ugly grey rectangles
•Image inheritance by black arrows
•Mounted volumes by blue lines, with a dot to show who’s the boss
•Linked containers by red lines (implying shared environment variables and
certainly a bit of scripting)
Baseimage
Architecture
The involved images are:
•Phusion, a lightweight, Docker oriented image based upon Ubuntu
•Baseimage: our base image adding a few common features
•Common web image (composer, git, PHP and so on…)
•Web: nginx
•Web dev: web developer tools (xdebug, XHProf, PHPUnit, PHPCS…)
•MySQL
•Let’s add PHPMyAdmin and XHProf separated containers
•Our project source code images:
–GMA (Go Math Academy) and CW (Curious World), relying upon PHP5.5
(ubuntu 14.04 images)
–ILW (iLearnWith) and C&M (Charly & Max) relying upon PHP5.3 (ubuntu
12.04 images)
–Each with their database images (embedding SQL dumps)
Architecture : a try with an nginx multi-projects architecture
Baseimage
1404
Baseweb
1404
Web
Symfony1.5
Web dev
Symfony1.5
Project
GMA
Project
ILW
XHProf
Phusion/
ubuntu1404
Phusion/
ubuntu1204
Baseimage
1204
Baseweb
1204
Web
Symfony1.0
Web dev
Symfony1.0
Project
CW
Project
C&M
MySQL
GMA db CW db
C&M db ILW db
PHPMy
Admin
Architecture : nginx multi-projects
•Classical unique nginx server holding many
websites
•The projects sources are builts as containers,
and shared as volumes
•The project sources also embed nginx
configuration files
•The DB dump is embedded in a
volume container
•A web server with dev/debug tools
inherits from the minimalist one
Baseimage
1404
Baseweb
1404
Web
Symfony1.5
Web dev
Symfony1.5
Project
GMA
XHProf
Phusion/
ubuntu1404
MySQL
GMA db
PHPMy
Admin
Architecture : nginx multi-projects
Improvements:
•Put together the database build scripts and the
project source
•Remove baseweb (was supposed to hold
only base build softwares like
PHP-cli and composer for a future
unit tests/builder container)
Web
Symfony1.5
Web dev
Symfony1.5
Project/DB
GMA
XHProf
Phusion/
ubuntu1404
MySQLPHPMy
Admin
Architecture : nginx multi-projects
In nginx.conf:
include /etc/nginx/sites-enabled/*/*.conf;
Allows to mount website configurations
as volumes from the project
container.
Project deployment at runtime, to
allow parametrizing according to
environment variables (composer
options for instance).
(suits our project configuration)
Web
Symfony1.5
Web dev
Symfony1.5
Project/DB
GMA
XHProf
Phusion/
ubuntu1404
MySQLPHPMy
Admin
Architecture : nginx multi-projects
Weaknesses:
•volume modifications may not be commited, bad
if we want to push tagged versions of the project
•The project cannot change anything in the web
file system (the fact of transmitting
project specific scripts was
considered but seemed twisty…)
•The web server must hold a large,
compatible configuration fitting
every project
•Web server/projects dependencies
that’s what Docker is designed to
prevent
Web
Symfony1.5
Web dev
Symfony1.5
Project/DB
GMA
XHProf
Phusion/
ubuntu1404
MySQLPHPMy
Admin
Architecture : nginx multi-projects
The counter-example of XHProf
Web Symfony1.5
php5-xhprof
php5-mcrypt
Other php5 libs
Xhgui.conf (nginx)
Project/DB GMA
XHGUI
php5-xhprof
php5-mcrypt
Xhgui.conf (nginx)
Only the sources and the nginx scripts are needed,
but composer must be run to load it, and expects
php5-mcrypt and php5-xhprof
php5-mcrypt and php5-xhprof must be the version
expected by XHGui. Dependency concerns?Must embed the requirements of every project
XHGui must set “auto_prepend_file=…” with the path to its sources for every project that use it (in nginx
fastcgi_params or PHP-FPM conf). Hard to do at startup (and in a parametrable way) if it’s an isolated container.
Architecture : nginx single-project
•nginx server running one project
•A project may inherit from the minimalist server
or from the dev server
•web tools, including XHGui are on the dev
version
•it is easy for a project to adapt configuration
files or extensions
•more Docker-friendly
Drawback: if a dev version of an image is
done, the dev version of the project doesn’t
inherit of the release one…
Baseimage
Web-php55
Symfony1.5
dev
Project
GMA dev
Phusion/
ubuntu1404
MySQL
PHPMy
Admin
Project
GMA
Symfony1.5
Architecture : nginx single-project
To address this issue, dev scripts may be
added to each image.
•any inheriting image may use it if needed
•a developer opening a bash session on
a container may launch one of these scripts
to deploy tools if needed
Drawback: changing a script affects the
child images, that need to be rebuilt (which
may take a long time).
Baseimage
Web-php55
Project
GMA dev
Phusion/
ubuntu1404
Project
GMA
Symfony1.5
install-dev-tools.sh
Installs zsh, wget, vim…
install-web-dev-tools.sh
Installs xdebug, xhprof…
install-web-php-tools.sh
Installs phpunit, phpmd,
phpcs, phpcsfixer…
runs install-dev-tools.sh,
install-web-dev-tools on build
Architecture : nginx single-project
Another point of this architecture:
how to add inheritance to the ENTRYPOINT
and RUN commands, and manage
environment variables at each level?
FROM tribalnova/baseimage
ADD files/startup.sh
/var/docker/startup.sh
ENTRYPOINT ["/var/docker/startup.sh"]
CMD nginx
Web-php55 Dockerfile
FROM tribalnova/web-php55
ADD files/project-startup.sh
/var/docker/web-startup.sh
ENTRYPOINT ["/var/docker/startup.sh"]
symfony15 Dockerfile
Baseimage
Web-php55
Project
GMA dev
Phusion/
ubuntu1404
Project
GMA
Symfony1.5
Architecture : nginx single-project
I combine the startup.sh scripts on build, using the shebang as a place holder:
#!/bin/sh
if [ $# -gt 0 ]; then
echo "Executing: $*"
$*
fi
Web-php55 Startup.sh
#!/bin/sh
some commands
if [ $# -gt 0 ]; then
echo "Executing: $*"
$*
fi
Web-php55 Startup.sh
#!/bin/sh
some commands
Symfony15 Startup.sh
RUN (perl -i -p -000 -e s@'#!/bin/sh'@"$(cat /var/docker/startup-web-dev.sh|sed -e
's///g'|sed 's/$/$/g')"@ /var/docker/startup.sh && rm /var/docker/startup-web-dev.sh)
Perhaps is there a simpler approach… Replacement in a script is a bit tricky(escaped characters).
Would be nice to have a PRERUN Docker instruction
Architecture : nginx single-project
It was also considered to use a init.d like
directory, or even the init system itself.
The Phusion base image embeds runit,
which allows to define simply startup scripts.
But concatenation allows to generate a
single startup.sh script, easy to read, launch
And debug when wandering inside the
container. And limiting the use of specific
features (runit) allows to switch to another
base image if needed.
Baseimage
Web-php55
Project
GMA dev
Phusion/
ubuntu1404
Project
GMA
Symfony1.5
Architecture : nginx single-project
Baseimage1404
Web-php55
Symfony1.5
Project
ILW
Phusion/
ubuntu1404
Phusion/
ubuntu1204
Baseimage1204
Web-php53
Symfony1.0
Project
C&M
MySQL
PHPMyAdmin
Project
ILW-dev
Project
C&M-dev
Project
CW
Project
GMA
Project
CW-dev
Project
GMA-dev
MongoDB
(for XHGui)
Full stack
Architecture : nginx single-project
Baseimage1404
Web-php55
Symfony1.5
Phusion/
ubuntu1404
Phusion/
ubuntu1204
Baseimage1204
Web-php53
Symfony1.0
Ressources sharing between close images
•Docker builds from a file called « Dockerfile »,
the name of the file cannot be anything else.
•The Dockerfile can only use ressource from
its directory or below, never upper.
•When building, Docker rejects links
Project Project2
Architecture : nginx single-project
Baseimage1404
Web-php55
Symfony1.5
Phusion/
ubuntu1404
Phusion/
ubuntu1204
Baseimage1204
Web-php53
Symfony1.0
Ressources sharing between close images
The only way I found to share ressources
(factorize) was to build « variants » of the
Dockerfile in a subdirectory and temporarily
place them in the main folder (would be nice
to be able to specify the Dockerfile name).
#!/bin/sh
SCRIPT_DIR=`readlink -f $(dirname $0)`
DOCKERFILE="$SCRIPT_DIR/../../Dockerfile"
if [ -f $DOCKERFILE ]; then
mv $DOCKERFILE "$DOCKERFILE.bak"
cp "$SCRIPT_DIR/Dockerfile" $DOCKERFILE
docker build -t tribalnova/baseimage-ubuntu1204 "$SCRIPT_DIR/../.."
mv "$DOCKERFILE.bak" $DOCKERFILE
fi
baseimage build.sh
Project Project2
Architecture : nginx single-project test procedure
Project
Run with env var UPDATE=install
Commit Project-stable (project with sources)
Build
Run test with env var UPDATE=install-dev
Karma Run karma tests
Run jMeter consistency tests
Tests
OK?
End
Push project-stable
yep
nope
Conventions
Our needs have led to a few conventions:
Scripts naming convention:
install-xxx.sh
Script meant to be executed on build
startup-xxx.sh
Script meant to be executed at runtime
Currently, every added ressource is put into
/var/docker
For ressources other than scripts, if possible, use
directories to sort them by feature/role.
Directory convention:
Image-name
• .dockerignore
• build.sh
• test.sh
• Dockerfile
Files
• Install-xxx.sh
• Startup-xxx.sh
• Other ressources (in subdirs)
Variants
Image-variant-name
• .dockerignore
• build.sh
• test.sh
• Dockerfile
Won’t be necessary if
the Dockerfile may be
specified
Vagrant
Providers/provisioners to build a virtual machine
AWS
Vagrant
Virtual Box VMWare
Chef +
recipes
Puppet +
modules
Shell scripts
Providers
Provisioners
Docker + Vagrant
Docker can be used as a vagrant provider and as a vagrant provisioner.
Even if seemingly opposed, somewhat outcomes to the same…
AWS
Vagrant
Virtual Box VMWare
Chef +
recipes
Puppet +
modules
Shell scripts
Providers
Provisioners
Docker
Docker
Docker + Vagrant provisioner
Deploys a virtual machine with a pre-installed Docker
See https://docs.vagrantup.com/v2/provisioning/index.html
Advantages:
•One command line to deploy a VM holding a full web development
environment: vagrant up
•Shared configuration (Vagrantfile)
•Vagrant configuration features: SSH, port forwarding, ressources allocation…
•Can be completed with other vagrant providers
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.provision "docker"
end Minimum Vagrantfile
Docker + Vagrant provisioner
Vagrant.configure("2") do |config|
config.vm.host_name = "docker"
config.vm.box = "ubuntu/trusty64"
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "puppet/manifests"
puppet.module_path = "puppet/modules"
puppet.manifest_file = "site.pp"
puppet.options = "--verbose"
end
config.vm.synced_folder "./docker", "/docker"
config.vm.synced_folder "../..", "/var/www/gma"
config.vm.provision "docker" do |d|
d.build_image "-t tribalnova/web-php55 /docker/web"
end
config.vm.network :forwarded_port, guest:80, host:80
end
Vagrantfile sample
Docker + Vagrant provider
Launches containers directly under Linux, or runs lightweight boot2docker
VMs to emulate them under Mac OS or Windows.
See http://docs.vagrantup.com/v2/docker/basics.html
Usage:
•To start a vagrant provider script: vagrant up –provider=docker
•To see logs: vagrant docker-logs
•To run a command: vagrant docker-run
Docker + Vagrant provider
Vagrant.configure("2") do |config|
config.vm.define "mysql" do |a|
a.vm.provider "docker" do |d|
d.name = "mysql"
d.image = "mysql:5.7.5"
d.ports = ["3306:3306"]
d.env = {"MYSQL_ROOT_PASSWORD" => "root"}
end
end
config.vm.define "jenkins" do |a|
a.vm.provider "docker" do |d|
d.name = "jenkins"
d.build_dir = "."
d.ports = ["8081:80"]
end
end
end
Vagrantfile sample
Docker + Vagrant provider
The vagrant provider has some drawbacks under Mac OS X and Windows:
It uses boot2docker images, that don’t allow ports to be forwarded when using
the ports parameter (may change in the future). To correct this behaviour,
Vagrantfile descriptors are to be designed for each machine that need such a
configuration, a somewhat heavy overload for something designed to be run
easily and independently of the host OS.
There are vagrant projects designed to fix this issue, but the Vagrantfile
configuration gets heavier:
https://vagrantcloud.com/yungsang/boxes/boot2docker
https://vagrantcloud.com/parallels/boxes/boot2docker
Docker + Vagrant provider
Vagrant.configure("2") do |config|
config.vm.define "jenkins" do |a|
a.vm.provider "docker" do |d|
d.name = "jenkins"
d.build_dir = "."
d.ports = ["8081:80"]
d.vagrant_vagrantfile = "./Vagrantfile.jenkins"
d.vagrant_machine = "dockerhost"
end
end
end
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.provision "docker"
# The following line terminates all ssh connections.
Therefore
# Vagrant will be forced to reconnect.
# That's a workaround to have the docker
command in the PATH
config.vm.provision "shell", inline:
"ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill"
config.vm.define "dockerhost"
config.vm.box = "ubuntu/trusty64"
config.vm.network "forwarded_port",
guest: 8081, host: 8081
config.vm.provider :virtualbox do |vb|
vb.name = "dockerhost"
end
end
Vagrantfile
Docker + Vagrant + PHPStorm
Docker as a vagrant provisioner
PHPStorm has a Vagrant plugin that allows to execute its basic actions. The
« start SSH session… » command offers the option to connect on the
Vagrant VM.
Docker + other tools
•Swarm: docker clustering https://github.com/docker/swarm
•Fig: docker groups http://www.fig.sh
•Ansible: orchestration http://www.ansible.com
•Serf: orchestration, clustering https://www.serfdom.io
•Etcd: orchestration, service discovery https://github.com/coreos/etcd
•Zookeeper: orcherstration http://zookeeper.apache.org
•HAProxy: load balancer http://www.haproxy.org
Hints: no GUI during build
• To automatically confirm the package installation
apt-get install –y package
• To disable console interactive GUIs when installing a package (default choices)
DEBIAN_FRONTEND=noninteractive
In the Dockerfile: ENV DEBIAN_FRONTEND noninteractive
• To let composer make default choices
composer install --no-interaction
• To pre-answer to interactive questions
echo "xxx yyy"|debconf-set-selections
• To reactivate console interactive GUIs when logged in:
echo 'export DEBIAN_FRONTEND=dialog' >> /etc/profile
echo 'export TERM=linux' >> /etc/profile
Hints: port forwarding
To help reaching linked container, it is often convenient to forward local network communication
towards this container. There are many tools for that, I use socat to avoid struggling with iptables.
If a container is linked, our images redirect localhost:<port> towards the corresponding container.
MySQL:
if [ ! -z $MYSQL_PORT_3306_TCP_ADDR ]; then
mkdir -p /var/run/mysqld
socat UNIX-LISTEN:/var/run/mysqld/mysqld.sock,fork,reuseaddr,unlink-early,user=root,group=root,mode=777
TCP:mysql:3306 &
fi
Memcache:
if [ ! -z $MEMCACHED_PORT_11211_TCP_ADDR ]; then
socat TCP-LISTEN:11211,fork,reuseaddr,user=root,group=root,mode=777 TCP:memcached:11211 &
fi
Graylog:
if [ ! -z $GRAYLOG_PORT_12201_UDP_ADDR ]; then
socat UDP4-RECVFROM:12201,fork UDP4-SENDTO:graylog:12201 &
fi
Hints: Github/Bitbucket API limit
Github and Bitbucket have API limits that disallow to load too much packages when not identified.
Project builds may easily hit these limits. To overcome it when using composer, choose to load
packages form source.
composer --dev install --prefer-source
Note that the –prefer-source option also include the git metadata.
To disable the git SSH warnings, create a file ssh_config in /etc/ssh, containing:
StrictHostKeyChecking no
Hints: Phusion insecure SSH
Enabling SSH may be useful in development, as it allows to run commands directly on the container,
ignoring the intermediate virtual machine. The IDE for instance may run remote PHPUnit tests and
gather its results directly through SSH.
To easily enable it on the container, create a script:
Call it from a container startup script if the environment variable SSH_INSECURE is set:
if [ -e /var/docker/startup-ssh-insecure.sh ] && [ ! -z $SSH_INSECURE ] && [
$SSH_INSECURE -eq 1 ]; then
/var/docker/startup-ssh-insecure.sh && rm /var/docker/startup-ssh-
insecure.sh
fi
Keep in mind that the Docker environment variables won’t be at disposal during an SSH session (so
it also concerns the locale environment variables that should be set in a bash startup file).
#!/bin/sh
rm -f /etc/service/sshd/down
/etc/my_init.d/00_regen_ssh_host_keys.sh
/sbin/my_init --enable-insecure-key &
startup-ssh-insecure.sh
Hints: RUN
• RUN may be between brackets or not
–RUN ["echo hop"]
–RUN echo hop
• If no brackets, the script is executed with sh –c
• The executed sh –c command doesn’t behave exactly as expected... The command seems to be
somewhat quoted or escaped.
• To remind: the sh interpreter has a limited syntax (no accolade, some shell functions like echo have
different/less functions)
Won’t display anything
RUN ["echo hop"]
Will display « hop »
RUN echo hop
Won’t write as expected in a file
RUN echo foo && echo bar > test
Will write as expected
RUN (echo foo && echo bar) > test
Hints: ENTRYPOINT/CMD
• CMD is executed only if ENTRYPOINT is between brackets.
• If ENTRYPOINT is between brackets, the file existence is checked with stats
• Behaves differently of RUN
• CMD/ENTRYPOINT are designed to accept only a single command
CMD is ignored
ENTRYPOINT /var/docker/startup.sh ls
CMD uname
Error: stat /var/docker/startup.sh ls: no such file or
directory
ENTRYPOINT ["/var/docker/startup.sh ls"]
CMD uname
Only ls is executed
ENTRYPOINT ["/var/docker/startup.sh"]
CMD ls && uname
Its works
ENTRYPOINT ["/var/docker/startup.sh"]
CMD ["apache2ctl -d /etc/apache2
-f /etc/apache2/apache2.conf -e info
-DFOREGROUND"]
Hints: explore an image
Docker images are always open (if their repository is available).
To explore an image, for instance to observe the content of a file before it is removed during the
build process:
• Search for a relevant version in the history
docker history test/anyimage:1.3.2
IMAGE CREATED CREATED BY SIZE
c89094ec2bf4 4 days ago /bin/sh -c #(nop) COPY file:7978b485faf6af1cc 1.544 kB
602e5ea7bbaf 4 days ago /bin/sh -c rm interesting-file 11 kB
8419f2b0e486 4 days ago /bin/sh -c #(nop) CMD [mysqld] 0 B
8e72632db815 4 days ago /bin/sh -c #(nop) EXPOSE map[3306/tcp:{}] 0 B
7834ba645aeb 4 days ago /bin/sh -c #(nop) ENTRYPOINT [/entrypoint.sh] 0 B
7d64a14cac57 4 days ago /bin/sh -c sed -Ei 's/^(bind-address|log)/#&/ 1.822 kB
299556685f43 4 days ago /bin/sh -c { 206 MB
• Run bash on this version by bypassing any entrypoint. This method is also ideal to debug a
container.
docker run -ti –u root --entrypoint bash 8419f2b0e486
Hints: good practices
• A startup script (runtime) should be repeatable, as it may be executed more than once if the
container is stopped and restarts:
–Don’t delete a line in a file, but comment it/uncomment it
–Test if a file exists before calling it
–Check and kill side running processes before launching them again
pidof php5-fpm; if [ $? -ne 1 ]; then killall php5-fpm; fi
–etc…
• The scripts used at build time don’t need to be repeatable, and it’s a good idea to suppress them,
as they will be of no use:
/var/docker/install-devtools.sh && rm /var/docker/install-devtools.sh
• Do environment variable tests and use the error output in startup scripts:
if [ ! -z $MONGODB_URL ]; then
sed -i "s%'db.host'.*$%'db.host' => 'mongodb://$MONGODB_URL',%" /var/www/xhprof/config/config.php
else
>&2 echo "Undefined MongoDB URL, specify the host with '-e MONGODB_URL=1.2.3.4:27017'"
fi
• In the Dockerfile, keep the long operations (package installation) at the top of the file, as it will save
time if the image needs to be rebuilt after a modification that comes after in the file
Conclusions so far
Despite its appearant simplicity, its intuitive interface and Dockerfile syntax, working with Docker
revealed an higher complexity than expected.
Working with Docker mainly mixes the complexity of Linux scripting/commands with the Docker
concepts and voluntary restrictions, sometimes turning the fact of thinking/deploying apps as
containers into a challenge:
• running background apps as foreground apps
• isolating interdependent apps not designed for that, communication via socket/volumes
• environment variable parameters to influence shell scripts/alter configuration
• security parameters, SSH key handling, API limits, …
• and so on…
However containerizing applications is often a great step towards scalibility (the remaining is a
matter of service discovery).
Docker is a recent and popular tool, growing fastly. Its features are going to expand, and its
restrictions might get leveraged in the future. We should keep a close eye on its upcoming
evolutions, side tools and potential forks.
Conclusions so far
Use cases so far:
• Project development: not as flexible as using a VM (built by provisioning), but allows to be sure that
the same configuration runs everywhere (packages, headers). Good if the developer just focuses
on the sources, less interesting if the developer wants for instance to tweak his configuration or use
custom tools. However the ephemeral nature of the container may still be a good point in such a
case.
• Side development depending on the project: if the project is a pre-requisite to a development (an
API), Docker is a good solution as it allows to deploy the complete stack quickly. Vagrant is
recommended in this case.
• Continuous integration: using docker is a very good solution in this case, as it avoids dealing with
the configuration of a development server, and allows to return a clean server after the operations
have run.

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Docker Tips And Tricks at the Docker Beijing Meetup
Docker Tips And Tricks at the Docker Beijing MeetupDocker Tips And Tricks at the Docker Beijing Meetup
Docker Tips And Tricks at the Docker Beijing Meetup
 
Docker and the Linux Kernel
Docker and the Linux KernelDocker and the Linux Kernel
Docker and the Linux Kernel
 
Docker and the Container Ecosystem
Docker and the Container EcosystemDocker and the Container Ecosystem
Docker and the Container Ecosystem
 
Real-World Docker: 10 Things We've Learned
Real-World Docker: 10 Things We've Learned  Real-World Docker: 10 Things We've Learned
Real-World Docker: 10 Things We've Learned
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 
Learn docker in 90 minutes
Learn docker in 90 minutesLearn docker in 90 minutes
Learn docker in 90 minutes
 
Using Docker to build and test in your laptop and Jenkins
Using Docker to build and test in your laptop and JenkinsUsing Docker to build and test in your laptop and Jenkins
Using Docker to build and test in your laptop and Jenkins
 
Docker based-pipelines
Docker based-pipelinesDocker based-pipelines
Docker based-pipelines
 
Learning Docker with Thomas
Learning Docker with ThomasLearning Docker with Thomas
Learning Docker with Thomas
 
Shipping Applications to Production in Containers with Docker
Shipping Applications to Production in Containers with DockerShipping Applications to Production in Containers with Docker
Shipping Applications to Production in Containers with Docker
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 
Docker at Djangocon 2013 | Talk by Ken Cochrane
Docker at Djangocon 2013 | Talk by Ken CochraneDocker at Djangocon 2013 | Talk by Ken Cochrane
Docker at Djangocon 2013 | Talk by Ken Cochrane
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 
Introduction to Docker, December 2014 "Tour de France" Bordeaux Special Edition
Introduction to Docker, December 2014 "Tour de France" Bordeaux Special EditionIntroduction to Docker, December 2014 "Tour de France" Bordeaux Special Edition
Introduction to Docker, December 2014 "Tour de France" Bordeaux Special Edition
 
Docker Continuous Delivery Workshop
Docker Continuous Delivery WorkshopDocker Continuous Delivery Workshop
Docker Continuous Delivery Workshop
 
Continuous Integration using Docker & Jenkins
Continuous Integration using Docker & JenkinsContinuous Integration using Docker & Jenkins
Continuous Integration using Docker & Jenkins
 
Containers: from development to production at DevNation 2015
Containers: from development to production at DevNation 2015Containers: from development to production at DevNation 2015
Containers: from development to production at DevNation 2015
 
Docker Introduction
Docker IntroductionDocker Introduction
Docker Introduction
 
Orchestrating Docker containers at scale
Orchestrating Docker containers at scaleOrchestrating Docker containers at scale
Orchestrating Docker containers at scale
 

Ähnlich wie Tribal Nova Docker feedback

2 Linux Container and Docker
2 Linux Container and Docker2 Linux Container and Docker
2 Linux Container and Docker
Fabio Fumarola
 

Ähnlich wie Tribal Nova Docker feedback (20)

Docker - Demo on PHP Application deployment
Docker - Demo on PHP Application deployment Docker - Demo on PHP Application deployment
Docker - Demo on PHP Application deployment
 
Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14Docker dev ops for cd meetup 12-14
Docker dev ops for cd meetup 12-14
 
Docker introduction
Docker introductionDocker introduction
Docker introduction
 
Docker+java
Docker+javaDocker+java
Docker+java
 
Getting Started with Docker
Getting Started with DockerGetting Started with Docker
Getting Started with Docker
 
Dockerizing a Symfony2 application
Dockerizing a Symfony2 applicationDockerizing a Symfony2 application
Dockerizing a Symfony2 application
 
Accelerate your development with Docker
Accelerate your development with DockerAccelerate your development with Docker
Accelerate your development with Docker
 
Accelerate your software development with Docker
Accelerate your software development with DockerAccelerate your software development with Docker
Accelerate your software development with Docker
 
Docker on Power Systems
Docker on Power SystemsDocker on Power Systems
Docker on Power Systems
 
Docker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los AngelesDocker 0.11 at MaxCDN meetup in Los Angeles
Docker 0.11 at MaxCDN meetup in Los Angeles
 
Super powered Drupal development with docker
Super powered Drupal development with dockerSuper powered Drupal development with docker
Super powered Drupal development with docker
 
Continuous Integration with Docker on AWS
Continuous Integration with Docker on AWSContinuous Integration with Docker on AWS
Continuous Integration with Docker on AWS
 
Containerization using docker and its applications
Containerization using docker and its applicationsContainerization using docker and its applications
Containerization using docker and its applications
 
Containerization using docker and its applications
Containerization using docker and its applicationsContainerization using docker and its applications
Containerization using docker and its applications
 
O'Reilly Software Architecture Conference London 2017: Building Resilient Mic...
O'Reilly Software Architecture Conference London 2017: Building Resilient Mic...O'Reilly Software Architecture Conference London 2017: Building Resilient Mic...
O'Reilly Software Architecture Conference London 2017: Building Resilient Mic...
 
Introduction to Docker Containers - Docker Captain
Introduction to Docker Containers - Docker CaptainIntroduction to Docker Containers - Docker Captain
Introduction to Docker Containers - Docker Captain
 
Red Hat Forum Benelux 2015
Red Hat Forum Benelux 2015Red Hat Forum Benelux 2015
Red Hat Forum Benelux 2015
 
Настройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'aНастройка окружения для кросскомпиляции проектов на основе docker'a
Настройка окружения для кросскомпиляции проектов на основе docker'a
 
Develop with docker 2014 aug
Develop with docker 2014 augDevelop with docker 2014 aug
Develop with docker 2014 aug
 
2 Linux Container and Docker
2 Linux Container and Docker2 Linux Container and Docker
2 Linux Container and Docker
 

Kürzlich hochgeladen

💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
nirzagarg
 
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
nilamkumrai
 
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
nilamkumrai
 
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
@Chandigarh #call #Girls 9053900678 @Call #Girls in @Punjab 9053900678
 
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
ydyuyu
 

Kürzlich hochgeladen (20)

Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
 
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
💚😋 Bilaspur Escort Service Call Girls, 9352852248 ₹5000 To 25K With AC💚😋
 
Real Escorts in Al Nahda +971524965298 Dubai Escorts Service
Real Escorts in Al Nahda +971524965298 Dubai Escorts ServiceReal Escorts in Al Nahda +971524965298 Dubai Escorts Service
Real Escorts in Al Nahda +971524965298 Dubai Escorts Service
 
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
2nd Solid Symposium: Solid Pods vs Personal Knowledge Graphs
 
Katraj ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For S...
Katraj ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For S...Katraj ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For S...
Katraj ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For S...
 
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
 
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
( Pune ) VIP Pimpri Chinchwad Call Girls 🎗️ 9352988975 Sizzling | Escorts | G...
 
Wagholi & High Class Call Girls Pune Neha 8005736733 | 100% Gennuine High Cla...
Wagholi & High Class Call Girls Pune Neha 8005736733 | 100% Gennuine High Cla...Wagholi & High Class Call Girls Pune Neha 8005736733 | 100% Gennuine High Cla...
Wagholi & High Class Call Girls Pune Neha 8005736733 | 100% Gennuine High Cla...
 
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
( Pune ) VIP Baner Call Girls 🎗️ 9352988975 Sizzling | Escorts | Girls Are Re...
 
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
 
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
WhatsApp 📞 8448380779 ✅Call Girls In Mamura Sector 66 ( Noida)
 
Real Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirtReal Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirt
 
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
𓀤Call On 7877925207 𓀤 Ahmedguda Call Girls Hot Model With Sexy Bhabi Ready Fo...
 
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
6.High Profile Call Girls In Punjab +919053900678 Punjab Call GirlHigh Profil...
 
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
 
Call Girls Sangvi Call Me 7737669865 Budget Friendly No Advance BookingCall G...
Call Girls Sangvi Call Me 7737669865 Budget Friendly No Advance BookingCall G...Call Girls Sangvi Call Me 7737669865 Budget Friendly No Advance BookingCall G...
Call Girls Sangvi Call Me 7737669865 Budget Friendly No Advance BookingCall G...
 
Al Barsha Night Partner +0567686026 Call Girls Dubai
Al Barsha Night Partner +0567686026 Call Girls  DubaiAl Barsha Night Partner +0567686026 Call Girls  Dubai
Al Barsha Night Partner +0567686026 Call Girls Dubai
 
Pune Airport ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready...
Pune Airport ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready...Pune Airport ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready...
Pune Airport ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready...
 
VVIP Pune Call Girls Sinhagad WhatSapp Number 8005736733 With Elite Staff And...
VVIP Pune Call Girls Sinhagad WhatSapp Number 8005736733 With Elite Staff And...VVIP Pune Call Girls Sinhagad WhatSapp Number 8005736733 With Elite Staff And...
VVIP Pune Call Girls Sinhagad WhatSapp Number 8005736733 With Elite Staff And...
 

Tribal Nova Docker feedback

  • 1. Docker feedback Feedback about Docker first experience at Tribal Nova 2015/01/19 Nicolas DEGARDIN <ndegardin@tribalnova.com>
  • 2. Overview • Docker intro • Docker • Architecture: nginx multi-projects • Architecture: nginx single project • Architecture: nginx single-project test procedure • Conventions • Vagrant • Docker + Vagrant • Docker + Vagrant provisioner • Docker + Vagrant provider • Docker + Vagrant + PHPStorm • Docker + other tools • Hints • Conclusions so far
  • 3. Docker intro What is Docker? A container management tool: Allows to embed an application and its dependencies in a virtual and portable container. Technologies involved: •cgroups •LXC (linux container) •AUFS (Another Unix File System) At the time of writing this document: Docker 1.4.
  • 4. Docker intro What is not Docker? A virtual machine management tool. A provisioning tool. Docker is voluntarily restrained to disallow build parametrizing. Technics involving generating/altering the build file make no sense: this is not the point of Docker, and there are better suited tools to serve this purpose.
  • 5. Docker intro My first objectives: •Full development environment quickly set up •Get rid of the dependencies problems •Unified configuration between developers/projects •Reusable containers for other purposes: –Deployable in other environments than DEV –Tests/continuous integration •Configurable containers •But keeping configuration simple (avoiding too heavy command lines/deep understanding of these containers) •Integrate the docker image inside the project •If possible, no adaptation to our projects configuration
  • 6. Docker Installation: •As a Linux package (lxc-docker) •With « boot2docker » under Windows and Mac OS – may not run directly under these environments as it is built upon Linux 2.6 kernel features – boot2docker is supposed to turn transparent the OS gap – boot2docker is really lightweight: no package manager. Not meant to be used as a host VM •Via a vagrant provisioner…
  • 7. Docker Images based upon Dockerfile, aimed at being hierarchical. No parametrization, no factorization (no includes, no reusable files) FROM … ADD… RUN … RUN ... ENTRYPOINT … CMD … FROM A ADD… RUN ... ENTRYPOINT … CMD … FROM … RUN ... FROM A ADD… RUN … RUN ... CMD … FROM B RUN… RUN ... A B C D
  • 8. Docker Containers can communicate via sockets, file volumes and environment variables. These communication modes are not bidirectionnal. first_container:A second_container:A third_container:B Volumes from second_container: the folders from the second container are visible in the first container Linked to third container: network features and env variables that allow socket communication
  • 9. Docker Note about volumes: •When a volume from a container is mounted into another one, both can read and write inside at runtime •A mounted volume can erase another one (or cover it – AUFS) •If the volume is defined during the build, files inside its directory may disappear (before or after the volume is defined, different behaviours have been observed for similar cases) •Volume files cannot be commited and are not inherited by child images So the developer should be cautious and avoid too audacious structures. I observed surprising/strange behaviours when experimenting for some edge cases. It also seems more secure to declare volumes when running the container.
  • 10. Architecture Here comes my feedback from different container architectures experimentations. I represent: •containers by ugly grey rectangles •Image inheritance by black arrows •Mounted volumes by blue lines, with a dot to show who’s the boss •Linked containers by red lines (implying shared environment variables and certainly a bit of scripting) Baseimage
  • 11. Architecture The involved images are: •Phusion, a lightweight, Docker oriented image based upon Ubuntu •Baseimage: our base image adding a few common features •Common web image (composer, git, PHP and so on…) •Web: nginx •Web dev: web developer tools (xdebug, XHProf, PHPUnit, PHPCS…) •MySQL •Let’s add PHPMyAdmin and XHProf separated containers •Our project source code images: –GMA (Go Math Academy) and CW (Curious World), relying upon PHP5.5 (ubuntu 14.04 images) –ILW (iLearnWith) and C&M (Charly & Max) relying upon PHP5.3 (ubuntu 12.04 images) –Each with their database images (embedding SQL dumps)
  • 12. Architecture : a try with an nginx multi-projects architecture Baseimage 1404 Baseweb 1404 Web Symfony1.5 Web dev Symfony1.5 Project GMA Project ILW XHProf Phusion/ ubuntu1404 Phusion/ ubuntu1204 Baseimage 1204 Baseweb 1204 Web Symfony1.0 Web dev Symfony1.0 Project CW Project C&M MySQL GMA db CW db C&M db ILW db PHPMy Admin
  • 13. Architecture : nginx multi-projects •Classical unique nginx server holding many websites •The projects sources are builts as containers, and shared as volumes •The project sources also embed nginx configuration files •The DB dump is embedded in a volume container •A web server with dev/debug tools inherits from the minimalist one Baseimage 1404 Baseweb 1404 Web Symfony1.5 Web dev Symfony1.5 Project GMA XHProf Phusion/ ubuntu1404 MySQL GMA db PHPMy Admin
  • 14. Architecture : nginx multi-projects Improvements: •Put together the database build scripts and the project source •Remove baseweb (was supposed to hold only base build softwares like PHP-cli and composer for a future unit tests/builder container) Web Symfony1.5 Web dev Symfony1.5 Project/DB GMA XHProf Phusion/ ubuntu1404 MySQLPHPMy Admin
  • 15. Architecture : nginx multi-projects In nginx.conf: include /etc/nginx/sites-enabled/*/*.conf; Allows to mount website configurations as volumes from the project container. Project deployment at runtime, to allow parametrizing according to environment variables (composer options for instance). (suits our project configuration) Web Symfony1.5 Web dev Symfony1.5 Project/DB GMA XHProf Phusion/ ubuntu1404 MySQLPHPMy Admin
  • 16. Architecture : nginx multi-projects Weaknesses: •volume modifications may not be commited, bad if we want to push tagged versions of the project •The project cannot change anything in the web file system (the fact of transmitting project specific scripts was considered but seemed twisty…) •The web server must hold a large, compatible configuration fitting every project •Web server/projects dependencies that’s what Docker is designed to prevent Web Symfony1.5 Web dev Symfony1.5 Project/DB GMA XHProf Phusion/ ubuntu1404 MySQLPHPMy Admin
  • 17. Architecture : nginx multi-projects The counter-example of XHProf Web Symfony1.5 php5-xhprof php5-mcrypt Other php5 libs Xhgui.conf (nginx) Project/DB GMA XHGUI php5-xhprof php5-mcrypt Xhgui.conf (nginx) Only the sources and the nginx scripts are needed, but composer must be run to load it, and expects php5-mcrypt and php5-xhprof php5-mcrypt and php5-xhprof must be the version expected by XHGui. Dependency concerns?Must embed the requirements of every project XHGui must set “auto_prepend_file=…” with the path to its sources for every project that use it (in nginx fastcgi_params or PHP-FPM conf). Hard to do at startup (and in a parametrable way) if it’s an isolated container.
  • 18. Architecture : nginx single-project •nginx server running one project •A project may inherit from the minimalist server or from the dev server •web tools, including XHGui are on the dev version •it is easy for a project to adapt configuration files or extensions •more Docker-friendly Drawback: if a dev version of an image is done, the dev version of the project doesn’t inherit of the release one… Baseimage Web-php55 Symfony1.5 dev Project GMA dev Phusion/ ubuntu1404 MySQL PHPMy Admin Project GMA Symfony1.5
  • 19. Architecture : nginx single-project To address this issue, dev scripts may be added to each image. •any inheriting image may use it if needed •a developer opening a bash session on a container may launch one of these scripts to deploy tools if needed Drawback: changing a script affects the child images, that need to be rebuilt (which may take a long time). Baseimage Web-php55 Project GMA dev Phusion/ ubuntu1404 Project GMA Symfony1.5 install-dev-tools.sh Installs zsh, wget, vim… install-web-dev-tools.sh Installs xdebug, xhprof… install-web-php-tools.sh Installs phpunit, phpmd, phpcs, phpcsfixer… runs install-dev-tools.sh, install-web-dev-tools on build
  • 20. Architecture : nginx single-project Another point of this architecture: how to add inheritance to the ENTRYPOINT and RUN commands, and manage environment variables at each level? FROM tribalnova/baseimage ADD files/startup.sh /var/docker/startup.sh ENTRYPOINT ["/var/docker/startup.sh"] CMD nginx Web-php55 Dockerfile FROM tribalnova/web-php55 ADD files/project-startup.sh /var/docker/web-startup.sh ENTRYPOINT ["/var/docker/startup.sh"] symfony15 Dockerfile Baseimage Web-php55 Project GMA dev Phusion/ ubuntu1404 Project GMA Symfony1.5
  • 21. Architecture : nginx single-project I combine the startup.sh scripts on build, using the shebang as a place holder: #!/bin/sh if [ $# -gt 0 ]; then echo "Executing: $*" $* fi Web-php55 Startup.sh #!/bin/sh some commands if [ $# -gt 0 ]; then echo "Executing: $*" $* fi Web-php55 Startup.sh #!/bin/sh some commands Symfony15 Startup.sh RUN (perl -i -p -000 -e s@'#!/bin/sh'@"$(cat /var/docker/startup-web-dev.sh|sed -e 's///g'|sed 's/$/$/g')"@ /var/docker/startup.sh && rm /var/docker/startup-web-dev.sh) Perhaps is there a simpler approach… Replacement in a script is a bit tricky(escaped characters). Would be nice to have a PRERUN Docker instruction
  • 22. Architecture : nginx single-project It was also considered to use a init.d like directory, or even the init system itself. The Phusion base image embeds runit, which allows to define simply startup scripts. But concatenation allows to generate a single startup.sh script, easy to read, launch And debug when wandering inside the container. And limiting the use of specific features (runit) allows to switch to another base image if needed. Baseimage Web-php55 Project GMA dev Phusion/ ubuntu1404 Project GMA Symfony1.5
  • 23. Architecture : nginx single-project Baseimage1404 Web-php55 Symfony1.5 Project ILW Phusion/ ubuntu1404 Phusion/ ubuntu1204 Baseimage1204 Web-php53 Symfony1.0 Project C&M MySQL PHPMyAdmin Project ILW-dev Project C&M-dev Project CW Project GMA Project CW-dev Project GMA-dev MongoDB (for XHGui) Full stack
  • 24. Architecture : nginx single-project Baseimage1404 Web-php55 Symfony1.5 Phusion/ ubuntu1404 Phusion/ ubuntu1204 Baseimage1204 Web-php53 Symfony1.0 Ressources sharing between close images •Docker builds from a file called « Dockerfile », the name of the file cannot be anything else. •The Dockerfile can only use ressource from its directory or below, never upper. •When building, Docker rejects links Project Project2
  • 25. Architecture : nginx single-project Baseimage1404 Web-php55 Symfony1.5 Phusion/ ubuntu1404 Phusion/ ubuntu1204 Baseimage1204 Web-php53 Symfony1.0 Ressources sharing between close images The only way I found to share ressources (factorize) was to build « variants » of the Dockerfile in a subdirectory and temporarily place them in the main folder (would be nice to be able to specify the Dockerfile name). #!/bin/sh SCRIPT_DIR=`readlink -f $(dirname $0)` DOCKERFILE="$SCRIPT_DIR/../../Dockerfile" if [ -f $DOCKERFILE ]; then mv $DOCKERFILE "$DOCKERFILE.bak" cp "$SCRIPT_DIR/Dockerfile" $DOCKERFILE docker build -t tribalnova/baseimage-ubuntu1204 "$SCRIPT_DIR/../.." mv "$DOCKERFILE.bak" $DOCKERFILE fi baseimage build.sh Project Project2
  • 26. Architecture : nginx single-project test procedure Project Run with env var UPDATE=install Commit Project-stable (project with sources) Build Run test with env var UPDATE=install-dev Karma Run karma tests Run jMeter consistency tests Tests OK? End Push project-stable yep nope
  • 27. Conventions Our needs have led to a few conventions: Scripts naming convention: install-xxx.sh Script meant to be executed on build startup-xxx.sh Script meant to be executed at runtime Currently, every added ressource is put into /var/docker For ressources other than scripts, if possible, use directories to sort them by feature/role. Directory convention: Image-name • .dockerignore • build.sh • test.sh • Dockerfile Files • Install-xxx.sh • Startup-xxx.sh • Other ressources (in subdirs) Variants Image-variant-name • .dockerignore • build.sh • test.sh • Dockerfile Won’t be necessary if the Dockerfile may be specified
  • 28. Vagrant Providers/provisioners to build a virtual machine AWS Vagrant Virtual Box VMWare Chef + recipes Puppet + modules Shell scripts Providers Provisioners
  • 29. Docker + Vagrant Docker can be used as a vagrant provider and as a vagrant provisioner. Even if seemingly opposed, somewhat outcomes to the same… AWS Vagrant Virtual Box VMWare Chef + recipes Puppet + modules Shell scripts Providers Provisioners Docker Docker
  • 30. Docker + Vagrant provisioner Deploys a virtual machine with a pre-installed Docker See https://docs.vagrantup.com/v2/provisioning/index.html Advantages: •One command line to deploy a VM holding a full web development environment: vagrant up •Shared configuration (Vagrantfile) •Vagrant configuration features: SSH, port forwarding, ressources allocation… •Can be completed with other vagrant providers Vagrant.configure("2") do |config| config.vm.box = "ubuntu/trusty64" config.vm.provision "docker" end Minimum Vagrantfile
  • 31. Docker + Vagrant provisioner Vagrant.configure("2") do |config| config.vm.host_name = "docker" config.vm.box = "ubuntu/trusty64" config.vm.provider "virtualbox" do |v| v.memory = 2048 v.cpus = 2 end config.vm.provision :puppet do |puppet| puppet.manifests_path = "puppet/manifests" puppet.module_path = "puppet/modules" puppet.manifest_file = "site.pp" puppet.options = "--verbose" end config.vm.synced_folder "./docker", "/docker" config.vm.synced_folder "../..", "/var/www/gma" config.vm.provision "docker" do |d| d.build_image "-t tribalnova/web-php55 /docker/web" end config.vm.network :forwarded_port, guest:80, host:80 end Vagrantfile sample
  • 32. Docker + Vagrant provider Launches containers directly under Linux, or runs lightweight boot2docker VMs to emulate them under Mac OS or Windows. See http://docs.vagrantup.com/v2/docker/basics.html Usage: •To start a vagrant provider script: vagrant up –provider=docker •To see logs: vagrant docker-logs •To run a command: vagrant docker-run
  • 33. Docker + Vagrant provider Vagrant.configure("2") do |config| config.vm.define "mysql" do |a| a.vm.provider "docker" do |d| d.name = "mysql" d.image = "mysql:5.7.5" d.ports = ["3306:3306"] d.env = {"MYSQL_ROOT_PASSWORD" => "root"} end end config.vm.define "jenkins" do |a| a.vm.provider "docker" do |d| d.name = "jenkins" d.build_dir = "." d.ports = ["8081:80"] end end end Vagrantfile sample
  • 34. Docker + Vagrant provider The vagrant provider has some drawbacks under Mac OS X and Windows: It uses boot2docker images, that don’t allow ports to be forwarded when using the ports parameter (may change in the future). To correct this behaviour, Vagrantfile descriptors are to be designed for each machine that need such a configuration, a somewhat heavy overload for something designed to be run easily and independently of the host OS. There are vagrant projects designed to fix this issue, but the Vagrantfile configuration gets heavier: https://vagrantcloud.com/yungsang/boxes/boot2docker https://vagrantcloud.com/parallels/boxes/boot2docker
  • 35. Docker + Vagrant provider Vagrant.configure("2") do |config| config.vm.define "jenkins" do |a| a.vm.provider "docker" do |d| d.name = "jenkins" d.build_dir = "." d.ports = ["8081:80"] d.vagrant_vagrantfile = "./Vagrantfile.jenkins" d.vagrant_machine = "dockerhost" end end end Vagrantfile Vagrant.configure("2") do |config| config.vm.provision "docker" # The following line terminates all ssh connections. Therefore # Vagrant will be forced to reconnect. # That's a workaround to have the docker command in the PATH config.vm.provision "shell", inline: "ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill" config.vm.define "dockerhost" config.vm.box = "ubuntu/trusty64" config.vm.network "forwarded_port", guest: 8081, host: 8081 config.vm.provider :virtualbox do |vb| vb.name = "dockerhost" end end Vagrantfile
  • 36. Docker + Vagrant + PHPStorm Docker as a vagrant provisioner PHPStorm has a Vagrant plugin that allows to execute its basic actions. The « start SSH session… » command offers the option to connect on the Vagrant VM.
  • 37. Docker + other tools •Swarm: docker clustering https://github.com/docker/swarm •Fig: docker groups http://www.fig.sh •Ansible: orchestration http://www.ansible.com •Serf: orchestration, clustering https://www.serfdom.io •Etcd: orchestration, service discovery https://github.com/coreos/etcd •Zookeeper: orcherstration http://zookeeper.apache.org •HAProxy: load balancer http://www.haproxy.org
  • 38. Hints: no GUI during build • To automatically confirm the package installation apt-get install –y package • To disable console interactive GUIs when installing a package (default choices) DEBIAN_FRONTEND=noninteractive In the Dockerfile: ENV DEBIAN_FRONTEND noninteractive • To let composer make default choices composer install --no-interaction • To pre-answer to interactive questions echo "xxx yyy"|debconf-set-selections • To reactivate console interactive GUIs when logged in: echo 'export DEBIAN_FRONTEND=dialog' >> /etc/profile echo 'export TERM=linux' >> /etc/profile
  • 39. Hints: port forwarding To help reaching linked container, it is often convenient to forward local network communication towards this container. There are many tools for that, I use socat to avoid struggling with iptables. If a container is linked, our images redirect localhost:<port> towards the corresponding container. MySQL: if [ ! -z $MYSQL_PORT_3306_TCP_ADDR ]; then mkdir -p /var/run/mysqld socat UNIX-LISTEN:/var/run/mysqld/mysqld.sock,fork,reuseaddr,unlink-early,user=root,group=root,mode=777 TCP:mysql:3306 & fi Memcache: if [ ! -z $MEMCACHED_PORT_11211_TCP_ADDR ]; then socat TCP-LISTEN:11211,fork,reuseaddr,user=root,group=root,mode=777 TCP:memcached:11211 & fi Graylog: if [ ! -z $GRAYLOG_PORT_12201_UDP_ADDR ]; then socat UDP4-RECVFROM:12201,fork UDP4-SENDTO:graylog:12201 & fi
  • 40. Hints: Github/Bitbucket API limit Github and Bitbucket have API limits that disallow to load too much packages when not identified. Project builds may easily hit these limits. To overcome it when using composer, choose to load packages form source. composer --dev install --prefer-source Note that the –prefer-source option also include the git metadata. To disable the git SSH warnings, create a file ssh_config in /etc/ssh, containing: StrictHostKeyChecking no
  • 41. Hints: Phusion insecure SSH Enabling SSH may be useful in development, as it allows to run commands directly on the container, ignoring the intermediate virtual machine. The IDE for instance may run remote PHPUnit tests and gather its results directly through SSH. To easily enable it on the container, create a script: Call it from a container startup script if the environment variable SSH_INSECURE is set: if [ -e /var/docker/startup-ssh-insecure.sh ] && [ ! -z $SSH_INSECURE ] && [ $SSH_INSECURE -eq 1 ]; then /var/docker/startup-ssh-insecure.sh && rm /var/docker/startup-ssh- insecure.sh fi Keep in mind that the Docker environment variables won’t be at disposal during an SSH session (so it also concerns the locale environment variables that should be set in a bash startup file). #!/bin/sh rm -f /etc/service/sshd/down /etc/my_init.d/00_regen_ssh_host_keys.sh /sbin/my_init --enable-insecure-key & startup-ssh-insecure.sh
  • 42. Hints: RUN • RUN may be between brackets or not –RUN ["echo hop"] –RUN echo hop • If no brackets, the script is executed with sh –c • The executed sh –c command doesn’t behave exactly as expected... The command seems to be somewhat quoted or escaped. • To remind: the sh interpreter has a limited syntax (no accolade, some shell functions like echo have different/less functions) Won’t display anything RUN ["echo hop"] Will display « hop » RUN echo hop Won’t write as expected in a file RUN echo foo && echo bar > test Will write as expected RUN (echo foo && echo bar) > test
  • 43. Hints: ENTRYPOINT/CMD • CMD is executed only if ENTRYPOINT is between brackets. • If ENTRYPOINT is between brackets, the file existence is checked with stats • Behaves differently of RUN • CMD/ENTRYPOINT are designed to accept only a single command CMD is ignored ENTRYPOINT /var/docker/startup.sh ls CMD uname Error: stat /var/docker/startup.sh ls: no such file or directory ENTRYPOINT ["/var/docker/startup.sh ls"] CMD uname Only ls is executed ENTRYPOINT ["/var/docker/startup.sh"] CMD ls && uname Its works ENTRYPOINT ["/var/docker/startup.sh"] CMD ["apache2ctl -d /etc/apache2 -f /etc/apache2/apache2.conf -e info -DFOREGROUND"]
  • 44. Hints: explore an image Docker images are always open (if their repository is available). To explore an image, for instance to observe the content of a file before it is removed during the build process: • Search for a relevant version in the history docker history test/anyimage:1.3.2 IMAGE CREATED CREATED BY SIZE c89094ec2bf4 4 days ago /bin/sh -c #(nop) COPY file:7978b485faf6af1cc 1.544 kB 602e5ea7bbaf 4 days ago /bin/sh -c rm interesting-file 11 kB 8419f2b0e486 4 days ago /bin/sh -c #(nop) CMD [mysqld] 0 B 8e72632db815 4 days ago /bin/sh -c #(nop) EXPOSE map[3306/tcp:{}] 0 B 7834ba645aeb 4 days ago /bin/sh -c #(nop) ENTRYPOINT [/entrypoint.sh] 0 B 7d64a14cac57 4 days ago /bin/sh -c sed -Ei 's/^(bind-address|log)/#&/ 1.822 kB 299556685f43 4 days ago /bin/sh -c { 206 MB • Run bash on this version by bypassing any entrypoint. This method is also ideal to debug a container. docker run -ti –u root --entrypoint bash 8419f2b0e486
  • 45. Hints: good practices • A startup script (runtime) should be repeatable, as it may be executed more than once if the container is stopped and restarts: –Don’t delete a line in a file, but comment it/uncomment it –Test if a file exists before calling it –Check and kill side running processes before launching them again pidof php5-fpm; if [ $? -ne 1 ]; then killall php5-fpm; fi –etc… • The scripts used at build time don’t need to be repeatable, and it’s a good idea to suppress them, as they will be of no use: /var/docker/install-devtools.sh && rm /var/docker/install-devtools.sh • Do environment variable tests and use the error output in startup scripts: if [ ! -z $MONGODB_URL ]; then sed -i "s%'db.host'.*$%'db.host' => 'mongodb://$MONGODB_URL',%" /var/www/xhprof/config/config.php else >&2 echo "Undefined MongoDB URL, specify the host with '-e MONGODB_URL=1.2.3.4:27017'" fi • In the Dockerfile, keep the long operations (package installation) at the top of the file, as it will save time if the image needs to be rebuilt after a modification that comes after in the file
  • 46. Conclusions so far Despite its appearant simplicity, its intuitive interface and Dockerfile syntax, working with Docker revealed an higher complexity than expected. Working with Docker mainly mixes the complexity of Linux scripting/commands with the Docker concepts and voluntary restrictions, sometimes turning the fact of thinking/deploying apps as containers into a challenge: • running background apps as foreground apps • isolating interdependent apps not designed for that, communication via socket/volumes • environment variable parameters to influence shell scripts/alter configuration • security parameters, SSH key handling, API limits, … • and so on… However containerizing applications is often a great step towards scalibility (the remaining is a matter of service discovery). Docker is a recent and popular tool, growing fastly. Its features are going to expand, and its restrictions might get leveraged in the future. We should keep a close eye on its upcoming evolutions, side tools and potential forks.
  • 47. Conclusions so far Use cases so far: • Project development: not as flexible as using a VM (built by provisioning), but allows to be sure that the same configuration runs everywhere (packages, headers). Good if the developer just focuses on the sources, less interesting if the developer wants for instance to tweak his configuration or use custom tools. However the ephemeral nature of the container may still be a good point in such a case. • Side development depending on the project: if the project is a pre-requisite to a development (an API), Docker is a good solution as it allows to deploy the complete stack quickly. Vagrant is recommended in this case. • Continuous integration: using docker is a very good solution in this case, as it avoids dealing with the configuration of a development server, and allows to return a clean server after the operations have run.