Skip to content

Docker Overview

Use containers to Build, Share and Run your applications !!!

Docker is an open platform for developing, shipping, and running applications.
Docker enables you to separate your applications from your infrastructure
so you can deliver software quickly.

Docker provides the ability to package and run an application
in a loosely isolated environment called a container.

The isolation and security allow you to run many containers simultaneously on a given host.
Containers are lightweight and contain everything needed to run the application,
so you do not need to rely on what is currently installed on the host.

You can easily share containers while you work, and be sure that
everyone you share with gets the same container that works in the same way

Docker Arichtecture
Docker Architecture

Basic commands

Cheat Sheet

Commands ...
        docker --help # to list all available options

        docker pull ${image}  # to get image from default docker registry: docker pull nginx
        # Build a image
        docker build -t ${image}:${tag} ./ # if Dockerfile is in the current folder
        docker build -t ${image}:${tag}  -f /path/to/Dockerfile # to specify path or custom file name
        ##  --build-arg bvar_name=value  to argument value if you use ARG in your Dockerfile
        docker history ${image}  # to see image build history

        docker run --name myconten  -i -t myimage /bin/bash
        docker exec -it ${container_name_or_id} bash #or bash or sh according to case# to enter inside container

        docker stop {container_name_or_id} # to stop
        docker start {container_name_or_id}

        docker ps   # to see the running containers
        docker ps -a  # to see all including stopped/crashed containers
        docker ps -f "status=exited" # to see only stopped containers
        is_runned=$(docker ps -q -f "name=${cont_name}")

        docker stop $(docker ps -a -q)  # stop all container
        docker stop $(docker ps -a -q)  # remove all container
        docker rmi $(docker images -q)  #remove all images.

        # Log in a registry

        docker login -u ${registry}

        # commit container changes into new image
        # useful when you manually change/add something
        #inside container and you want to save/keep it for next time
        docker commit - a="auteur" -m="message" {container_name_or_id} ${new_image}

        # copy file between server and container
        docker cp myfile   {container_name_or_id}:/dst/myfile #from server to container
        docker cp {container_name_or_id}:/dst/myfile  //myfile

        docker export containerID > filename.tar  # Export a container’s filesystem as a tar archive
        docker save imageID > filename.tar  # Save one or more images to a tar archive 
        # or like
        docker save -o filename.tarr imageID

        docker load <  filename.tar   # Load an image from a tar archive or STDIN
        docker load --input filename.tar

        docker inspect ${container_name_or_id} # to see container conf details
        docker inspect --format='{{json .State.Health}}' ${container_name_or_id}

        # docker import: Import the contents from a tarball to create a filesystem image
        docker import  filename.tar
        cat filename.tar| docker import - ${new name}

        ## You can also clone an exisitng server filesystem to use it to create image
        ## Example below

Archive existing server filesystem and import it as Docker image

Archiche server FS and create Docker image
        ## You must exclude some system folder like: sys, proc, dev/pts, mnt
        ## Then you can exclude another folders if you want

        cd /mnt

        tar -cvpf fullbackup.tar --directory=/ --exclude=proc --exclude=sys --exclude=dev/pts --exclude=tmp --exclude=backups \
        --exclude=mnt  --exclude=home/osadmin --exclude=lost+found --exclude=images --exclude=media --exclude=users --exclude=opt \
        --exclude=var/log --exclude=var/lib/docker --exclude=var/log/docker  --exclude=usr/tmp --exclude=usr/lib/vmware-tools \
        --exclude=usr/lib/firmware --exclude=usr/share/doc .

        # Import archive as Docker image
        cat fullbackup.tar | docker import - myserverclone:1.0.0

Docker Group for Non-root users

Create a docker group to enable non-root users to run docker commands without using sudo

Create docker group and add a user
    # Create the docker group if it doesn't exist
    sudo groupadd docker

    # Add a $USER to the group
    sudo usermod -aG docker $USER

    # Log in to the docker group
    newgrp docker

    # Test with a non-root user
    docker info

Ubuntu - DEBIAN_FRONTEND

ENV DEBIAN_FRONTEND noninteractive
When you use debian or ubuntu as base in Dockerfile you should add this
to avoid interactive rquest otherwise the image build will fail

Docker insecure registry

If you want to use your own docker registry you should add it in daemon.json`` as insecure registry.

Modify or create /etc/docker/daemon.json and add
    {
    "insecure-registries" : ["myregistrydomain.com:5000"]
    }

Change data-root - /var/lib/docker

Sometimes you want to change /var/lib/docker folder to another folder

Create folder and stop Docker
    mkdir –p  /path/newfolder
    chmod 701 /path/to/newfolder
    service docker stop
    # if you already have docker data: images/containers and you want to keep
    ## you can copy /var/li/docker content in the new one like
    sudo rsync -aP /var/lib/docker/  /path/newfolder

Then modify or create /etc/docker/daemon.json to add key data-root (graph if you use an old version) to specify your new folder

Update daemon.json
        vim /etc/docker/daemon.json # Create if does not exist yet and add this:
            {
            "storage-driver": "overlay2"   ## an already existing key in my case
            ,"data-root": "/path/newfolder"  ##added to change /var/docker/

            }

        # Start a Docker service
        service docker start

        # you can now delete /var/lib/docker

Use Docker behind Proxy

When your server need proxy to access to external, docker pull will not work.
But you can use proxy settings to achieve that:
https://docs.docker.com/config/daemon/systemd/#httphttps-proxy

Setup HTTP Proxy
    sudo mkdir -p /etc/systemd/system/docker.service.d

    cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
    Environment="HTTP_PROXY=http://proxy.example.com:80"
    Environment="HTTPS_PROXY=https://proxy.example.com:443"
    Environment="NO_PROXY=localhost,127.0.0.1,xxx"
    EOF
Socks5 Proxy
# Sometimes you need a socks proxy instead of hhtp/https one

## Linux
Environment="ALL_PROXY=socks5://127.0.0.1:8899/"

sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker  # to verify configuration

## Open sock tunnel proxy based on port 8899
sshpass -p password ssh -D 8899 -f -C -q -N user@ip
Socks5 Proxy
## Windows
[Environment]::SetEnvironmentVariable("ALL_PROXY", "socks5://127.0.0.1:666/", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("NO_PROXY", "localhost,127.0.0.1", [EnvironmentVariableTarget]::Machine)

Restart-Service docker

Update a logical volume used by docker [RedHat]

This assumes you are using devicemapper driver which uses a logical volume

Already experimented with this case with Red Hat servers where the /var/lib/docker
was mounted on a dedicated logical volume(LV).

More about devicemapper driver in production here

Use case example

Chosen VG: infravg car plus d'espace

Pre-Setup
    systemctl stop docker
    rm -rf /var/lib/docker # if you don't want to keep existing things
    # or mv /var/lib/docker /var/lib/docker.old # to keep it
/etc/docker/daemon.json
Directly with `/etc/docker/daemon.json`

    # ${DEVICE} is a PV (hysical volume) to use to create a Docker LV

    vim /etc/docker/daemon.json
    # and 
    {
    "storage-driver": "devicemapper",
    "storage-opts": [
        "dm.directlvm_device=${DEVICE}",
        "dm.thinp_percent=95",
        "dm.thinp_metapercent=1",
        "dm.thinp_autoextend_threshold=80",
        "dm.thinp_autoextend_percent=20",
        "dm.directlvm_device_force=false"
    ]
    }

    service docker start
/etc/sysconfig
According to your system settings
(Applied on Red Hat server some years ago)

    cd /etc/sysconfig
    vim docker-storage-setup ## add The VG you wan to use (infravg)
    vim docker-storage  # leave OPTIONS as blank
    docker-storage-setup  # will create a Docker LV for you
    #lvdisplay

    service docker start
lv commands
if you want to create docker LV by yourself

    lvdisplay # to have details about existing logical volume
    pvdisplay # to have details about pv

    ## here i use a VG called: infravg

    lvcreate --wipesignatures y -n thinpool infravg -l 45%VG    #22,5 GB
    ## lvremove /dev/mapper/infravg-thinpool  # to delete a lv if needed

    lvcreate --wipesignatures y -n thinpoolmeta infravg -l 5%VG   #2,5 GB
    lvconvert -y --zero n -c 512K --thinpool infravg/thinpool --poolmetadata infravg/thinpoolmeta

    cd /etc/lvm/profile
    vim infravg--docker-pool-extend.profile
    ###  and then  specify thin_pool_autoextend_threshold and thin_pool_autoextend_percent values

    lvchange --metadataprofile infravg--docker-pool-extend infravg/thinpool
    ## Udpdate docker storage confile with the new LV path

    sudo lvs -o+seg_monitor  ## Assure lv monitoring is enabled
    sudo lvchange --monitor y docker/thinpool

    ## Accrding to your case you should update the LV path
    vim /etc/sysconfig/docker-storage 
    ## add /dev/mapper/infravg-thinpool

    service docker start

Basic Exercices

Basic Apache Website

create index.php
        ## create index.php
        cat > index.php << EOF
        <!DOCTYPE html>
        <html>
        <head>
            <title> Check system </title>
        </head>
        <body>
        <p> Welcome: I am a PHP-APACHE Container! </p>

        <?php
        echo "<h5> System Info </h5>";
        echo " ";
        $unam = shell_exec('uname -a');
        echo "<pre>$unam</pre>";
        $lscpu = shell_exec('lscpu | head -23');
        echo "<pre>$lscpu</pre>";
        ?>

        <?php
        echo "<h5> Load average </h5>";
        echo " ";
        $uptim = shell_exec('uptime');
        echo "<pre>$uptim</pre>";
        echo " "
        ?>

        <?php
        echo "<h5> CPU and MEM </h5>";
        echo " ";
        $cpumem = shell_exec('top -b -n1 | head -3');
        echo "<pre>$cpumem</pre>";
        echo " "
        ?>

        <?php
        echo "<h5> top </h5>";
        echo " ";
        $top = shell_exec('top -b -n1');
        echo "<pre>$top</pre>";
        echo " "
        ?>

        <?php
        echo "<h5> Stockage </h5>";
        echo " ";
        $free = shell_exec('free');
        echo "<pre>$free</pre>";
        $dfh = shell_exec('df -h');
        echo "<pre>$dfh</pre>";
        echo " "
        ?>

        <?php
        echo "<h5> Users list </h5>";
        echo " ";
        $userlist = shell_exec('cut -d: -f1 /etc/passwd');
        echo "<pre>$userlist</pre>";
        echo " "
        ?>

        </body>
        </html>
        EOF

        docker run -d -p 80:80 --name my-app -v "$PWD":/var/www/html php:7.0-apache

        # visit http://localhost or http://${server_ip}
        ```
exo-00: docker cli
    tests somme commands:
    docker, info docker images, docker ps; docker ps -a, docker inspect,
    docker run, docker logs, docker stop docker rm, docker volume ls

    [Discover CLI command](https://docs.docker.com/engine/reference/commandline/docker/){:target="_blank"}
    pratical test: https://katacoda.com/alvagante/scenarios/3
exo-01: Run Docker containers
    More about [docker run command](https://docs.docker.com/engine/reference/run/#general-form){:target="_blank"}

    Pratical test [HERE](https://katacoda.com/allamand/courses/docker-course/docker-basics){:target="_blank"},

    do **only** from step **1** to step **3** (1, 2 and 3)
exo-02: Dockerfile, build image and run container
    learn dockerfile: https://docs.docker.com/engine/reference/builder/#usage
    Only Step4: katacoda: https://katacoda.com/allamand/courses/docker-course/docker-basics

    Build image in our server(not in katacoda) with Dockerfile

        1. write a simple html file
        2- write a Dockerfile 
                *** use httpd base image to deploy a basic web site: 
             static base image: amp-prod-repo-artifacts.equant.com:5005/orange/httpd-mime:1.0 
         
            ** add or copy your source file in your image: 
        3 build your image

        4 run your container 
          **change  your web site port 8081 
          create a docker volume "myvolume" see docker volume.. 
          using it by mounting the /var/www/html/
exo-03: Write complex Dockerfile
    ## run ubuntu container
    image: docker.io/ubuntu:latest

    ## To run 
      docker run --name ubuntu -d docker.io/ubuntu:latest tail -f /dev/null 
     # to enter inside 
     docker exec -it ubuntu bash 
     #the container ubuntu: is equivalent(like) of your machine/vm/server with OS ubuntu 
      
     ## first step: 
       a- enter inside: 
          install apache, deploy a simple html page(index.html) 
          then: install PHP and try to deploy now a dynamique page(index.php) 
           { you can do this directly by skipping html step if you want}
        b: you have finished to deploy all web services in your server ubuntu

    ## second step:
        Now write a Dockerfile to do all manual actions you do above inside container
        to allow another one to have an ready image with theses services

    ## deploy your website with docker run  to test it
Exo-04: Deploy with docker-compose.yml
    !!! Read only page content, DON'T FOLLOW its sub links

    about docker-compose: https://docs.docker.com/compose/overview/
    command docker-compose: https://docs.docker.com/compose/reference/overview/
    docker-compose file
        version2: https://docs.docker.com/compose/compose-file/compose-file-v2/
        version3: https://docs.docker.com/compose/compose-file/

    Only step5 katacoda: https://katacoda.com/allamand/courses/docker-course/docker-basics

    Write on our server, write docker-compose.yml to deploy you exercice2 website
dockerfile ubuntu
    FROM docker.io/ubuntu:latest

    LABEL MAINTAINER="xxx" \
        Version="xxx" \
        Name="xxx" \
        Vendor="xxx"

    ## pour le dpkg
    ENV DEBIAN_FRONTEND noninteractive
    USER root

    RUN apt-get update && \
        apt-get install apache2 apache2-doc apache2-utils -y && \
            apt-get install php -y && \
            apt-get install apt-utils -y &&\
            apt-get install vim -y && \
            apt-get install curl -y

    #ajout de conf pour example.conf
    ADD example.com.conf /etc/apache2/sites-available

    RUN echo "Europe/Paris" > /etc/timezone && \
        dpkg-reconfigure -f noninteractive tzdata && \
        a2dissite 000-default.conf && \
        mkdir -p /var/www/example.com/public_html && \
        mkdir /var/www/example.com/logs

    COPY index.php /var/www/example.com/public_html/
    ADD start.sh /tmp/

    RUN a2ensite example.com.conf && \
        chmod 777 /tmp/start.sh
    CMD /tmp/start.sh

    ## start.sh
    #!/bin/bash
    service apache2 start &
    while true
    do
            echo "coucou, je suis toto"
            sleep 1
    done