All you need is ...
a Docker Container !

What is Docker?

Docker is a virtualization software


It uses features provided by Linux kernel, likes cgroups and Namespaces, to isolate Applications


Faster delivery of your applications



Ok but... it's like a Virtual Machine!

Why Docker?

Virtual machines suck?
a bit

  • CPU and RAM hungry
  • Not really maintenable
  • Slow down your workflow

Virtual Machine Work flow

I need to test/develop my App in XYZ environment

  1. Choose a distro
  2. Set all hardware stuff for the virtual machine (ram, hd, network, ...)
  3. Install an entire OS
  4. Configure OS (port forwarding, shared folder, ...)
  5. Install applications for the environment
  6. Configure applications
  7. Do they work at the first time?
  8. Configure applications part 2
  9. And finally... Test your App!


And if I want to test in a XY.. β environment ??

Docker is different

Same App in XYZ environment

  1. Download (o create) images which contain X, Y, Z (one application for image)
  2. Create containers from the images
  3. Connect and Run X, Y, Z containers
  4. Test your App!


And if I want to test in a XY.. β environment ??

  1. Download (o create) image which contain β
  2. Create container from the image
  3. Connect and Run X, Y, β containers
  4. Test your App!


It seems to be easy...

Hands-on NOW! OSX

  • Download Boot2Docker from http://boot2docker.io/
  • Open a Terminal and run
    
    $ boot2docker init
    $ boot2docker start
    $ $(boot2docker shellinit)
    
    # useful tip
    $ echo $(boot2docker ip) dockerhost | sudo tee -a /etc/hosts
    									
  • Have a fun with Docker!
    
    $ docker run --rm -v "$(pwd)":/pippo ubuntu:trusty  ls pippo
    									

Hands-on NOW! Linux

  • Depends of your distro:
  • Debian
    
    $ sudo apt-get update
    $ sudo apt-get install docker.io
    								
  • ArchLinux
    
    $ sudo pacman -S docker
    $ sudo systemctl start docker #for start docker
    								
  • Ubuntu
    
    $ curl -sSL https://get.docker.com/ubuntu/ | sudo sh
    								

Have a fun with Docker!


$ docker run --rm -v "$(pwd)":/pippo ubuntu:trusty  ls pippo
									

What we just did?


$ docker run --rm -v "$(pwd)":/pippo ubuntu:trusty  ls pippo
									

We tell docker to do:

  • Launch a command inside the container
    ls pippo
  • Use a specific ubuntu version (if not locally present, it'll be downloaded)
    ubuntu:trusty
  • Share current folder, and mount the folder inside the container (RW) at path /pippo
    -v "$(pwd)":/pippo
  • After command executing, delete the container
    --rm
  • Last command... run this thing!

More options, more fun!

docker run -t -i ubuntu:14.04 /bin/bash
  • -t : pseudo-tty or terminal inside container
  • -i : use STDIN for inteact with container

docker run -d -P --name web training/webapp python app.py
  • -d : run the container in the background
  • -P : map network ports inside our container to our host
  • or -p 5000:5000 : map port 5000 inside our container to port 5000 on our local host
  • --name web : set container name

Manage Images and Containers


# List all downloaded images
$ docker images

# Delete images
docker rmi image_name

# List all containers
$ docker ps -a
# -a : show all containers (running and stopped)

# Delete containers
$ docker rm container_name

# Start a container
$ docker start container_name

# Attach to a container
docker attach container_name

Under the Hood

Docker is made of:

  • Layers : read-only or read-write file system
  • Images : read-only Layer. An image can be a result of multiple (read-only) layers stacked on top of each other
  • Containers : process launched inside a read-write layer on top of all read-only layer

Debian image

debian image

Container over Debian Image

container over debian image

Container stacked layer

container multylayer

You can commit your modification inside an image using:

docker commit -m="Added some gem" -a="Cris" id_container new_name_image:version

Cool stuff: Linking container


$ docker run -d --name db training/postgres
$ docker run -d -P --name web --link db:db training/webapp python app.py
# option --link name:alias

"db" container exposes port 5432 which is automatically connected to "web" container


Docker exposes connectivity information for the source to the recipient using :

  • Environment variables
  • Updating the /etc/hosts file


You can use these variables inside your applications

Cool stuff: Data Volumes

Useful to persist or share data


$ docker run -ti --name keep_data -v /pippo busybox
# create a new volume inside container

$ docker run -ti --name keep_data -v /src/webapp:/pippo:ro busybox
# mount /src/webapp inside a container but read-only

Share Data Volumes


$ docker run -ti --name db_vol -v /var/lib/mysql busybox
# create a new volume inside container

$ docker run -d --volumes-from db_vol --name mysql_1 -p 3306:3306 tutum/mysql
# mount /var/lib/mysql inside container mysql_1
						

DockerFile: make images portable

You can define a Dockerfile where inside there are all the commands you need to create an image

In Dockerfile you can:

  • define your base image
  • set environment variables
  • run command for install/edit image configuration
  • add file from host to image
  • set volumes
  • expose application ports


Create the image with command


$ docker build -t="myuser/myapp:v1" .
# inside the directory where there is Dockerfile
						

An Example


# random instructions!!

FROM ubuntu:trusty
MAINTAINER Tony, Bepi

# Install packages
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
  apt-get -yq install mysql-server-5.6 pwgen && \
  rm -rf /var/lib/apt/lists/*

# Install other packages
ENV VERSION 4.7.2
ENV APP app-$VERSION
RUN curl --retry 3 http://example.com/$VERSION/$APP.tgz > /opt/$APP.tgz
RUN tar -C /opt --extract --file /opt/$APP.tgz
RUN mv /opt/$APP /opt/my_app

# Add scripts
ADD run.sh /run.sh
RUN chmod 755 /*.sh

# Add VOLUMEs to allow backup of config and databases
VOLUME  ["/etc/mysql", "/var/lib/mysql"]

# Add a user
RUN useradd --home-dir /opt/my_app --comment "my_app Server" custom_user
RUN chown -R custom_user:custom_user /opt/my_app/example

# user when container is up
USER custom_user

EXPOSE 3306
CMD ["/run.sh"]
#WORKDIR /opt/my_app
#CMD ["java", "-jar", "start.jar"]

							

It's ok... but could be better!

Docker Hub

Docker Hub is a remote repository
where you can find (public) images and you can commit your images in order to share with another user!

You can create and share images privately with your organization



$ docker search ruby
# search for images tagged "ruby"

$ docker pull rails
# download the "rails" images

$ docker commit -m "Added package β " id_container new_name_image:version
# add a new package

$ docker push new_name_image:version
# push image to docker hub
						


Fig: ONE command away from a running environment

Fig let you to define all the containers
for your application in one file


dbvol:
    image: busybox
    volumes:
        - /var/lib/mysql

mysql:
    build: docker/mysql
    volumes_from:
        - dbvol
    ports:
        - "3306:3306"

phpapache:
    build: docker/apache_php
    volumes:
        - .:/app
    ports:
        - "8080:80"
    links:
        - mysql:mysql
						

Inside the directory run


$ fig up
# build, (re)create, start and attach to containers for a service.

							


Fig is still a young tool
It'll be part of docker from the next release

It's time to test!

Test docker in your workflow


Discuss, create Dockerfile, and share knowledge

Resources

Thank You