Docker Tutorial

What is Docker and Why

Docker is a tool to create, deploy, and run applications without any fallbacks about different production environment.it’s a bit like VM but unlike it, you can see the difference between Docker and VM in below image. Container runs on Host os but VM run in separate OS and waste your resource. alt text

How to install Docker on linux

Update the apt package index:

sudo apt-get update

Install packages to allow apt to use a repository over HTTPS

 sudo apt-get install  apt-transport-https ca-certificates  curl  software-properties-common

Add Docker’s official GPG key:

 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo apt-key fingerprint 0EBFCD88

get last version from repository

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu   $(lsb_release -cs) stable"

update and install

sudo apt-get update
sudo apt-get install docker-ce

Create docker image

create Dockerfile

Each docker file is a script to creating the image

FROM : define base image like ubuntu

MAINTAINER : declare the author

RUN : it takes to command and run it .it used to build image . For example install, its run during the build time

CMD : used for executing a specific command, it uses for initial, default command that gets executed and run command not in during build time

ENTRYPOINT : the first command executed after creating image

Add : get two arguments, source, and destination, copy from host to container if the source is URL its download from the web

ENV : declate environemt variable example # Usage: ENV key value

WORKDIR : set working directory for CMD Command

EXPOSE : The EXPOSE command is used to associate a specified port to enable networking between the running process inside the container and the outside world

VOLUME : create volume for container

example create Dockerfile

FROM openjdk:8u171-jre-alpine3.8
ADD target/myApp.jar myApp.jar
ENTRYPOINT ["java","-jar","/myApp.jar"]
EXPOSE 8085

then you can create localy image

docker build --tag=myappco:1 .

run docker image

docker run --name=config-server --publish=8086:8085  myappco:1

port 8086 is external port -it – enable interactive mode -d – detach from the container after booting

if you have multi app and they work together you should create a network for them or create link between them

Docker stages

create automation for create java app , you can use stage to create automation for create java application we use openjdk:8-jre-alpine for image becuase it’s smallest image

Example for create stage

FROM alpine/git as clone
WORKDIR /app
RUN git clone https://github.com/rasoulpoordelan/dockerTestAutomation.git

FROM maven:3.5.4-jdk-8-alpine as build
WORKDIR /app
COPY --from=clone /app/dockerTestAutomation /app
RUN mvn clean package

FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=build /app/target/myapp.jar /app
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/myapp.jar"]

Network

Network is one of most challenging skill on the docker we have two type network in docker single host and cluster. by default, docker container connects to the default network in the same host and can be accessed from that host and IP. you can create your own network for your application work together and find each other with the name on the network. we have a bridge network in the same host and overlay network for the cluster. every container in default bridge can connect each other with IP but in user definition network they can find each other by name and all ports are accessible.

Create new network and connect to that

docker network create my-net
docker network connect my-net my-app 

create a bridge network

docker network create -d bridge mynet

create an overlay network for use with swarm services, use a command like the following:

 docker network create -d overlay my-overlay

To create an overlay network which can be used by swarm services or standalone containers to communicate with other standalone containers running on other Docker daemons, add the –attachable flag:

docker network create -d overlay --attachable my-attachable-overlay

Get network list

docker network ls 

Inspecting a Docker network

docker network inspect networkname 

Docker volume

With Docker volume we can manage our data within Docker continer.continer have space to save your data but when you remove it all data in continer is removed and the other hand you can use it for share data between continer.

best way : use –mount insted of -v or volume to assign to continer

create volume

docker create volume myvol

show volume

docker volume inspect myvol

assign to continer

$ docker run -d   --name devtest  --mount source=myvol,target=/app  nginx:latest

If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume. The container then mounts and uses the volume, and other containers which use the volume also have access to the pre-populated content.

Docker Compose

ocker Compose is used to run multiple containers as a single service, for example, you have application have dependencies to NGINX and Postgress you can create a compose file to create them as service. Docker Compose is a YAML File docker-compose.yml. you can create it with any editor. Docker Compose have version

The directory structure will look like this:

simple_app
├── content
│    ├── Dockerfile
│    └── code
│         ├── simple_app.py
│         └── requirements.txt
└──  docker-compose.yml

Three steps to using Docker Compose

  • define each service in a Docker file
  • define the services and their relation on YAML file
  • docker-compose up

Build Image (if an appropiated dockerfile is existed)

docker-compose build

Scale Running containers

docker-compose scale SERVICE=3

all command existed

	build Build or rebuild services
	kill Kill containers
	help Get help on a command
	logs View output from containers
	port Print the public port for a port binding
	ps List containers
	pull Pulls service images
	rm Remove stopped containers
	run Run a one-off command
	scale Set number of containers for a service
	start Start services
	stop Stop services
	restart Restart services
	up Create and start containers

create a simple compose

we have frontend from Redis Commander and connected that to Redis

it’s our YAML file

backend: 
  image: redis:3 
  restart: always

frontend: 
  build: commander 
  links: 
    - backend:redis  
  ports: 
    - 8090:8081 
  environment: 
    - VAR1=value 
  restart: always

the run it

docker-compose up -d

it’s run a command like this

docker build -t commander commander
docker run -d --name frontend -e VAR1=value -p 8090:8081
   --link backend:redis commander

docker-compose up -d builds images if needed. docker-compose ps shows running containers. docker-compose stop stop services

Docker Swarm

Docker have natively swarm mode for managing a cluster of Dockers.

preperation

create master swarm(first node)

docker swarm init --advertise-addr MANAGER_IP

for getting a token to join

docker swarm join-token worker
docker swarm join-token manager

joining to swarm use the above code to join to swarm

How to create and manage service

docker service create --replicas 5 -p 80:80 --name web myApp
get service status
docker service ls

get specific service status

docker service ps myApp

change scale service

docker service scale myApp=8

applying rolling update

docker service update --image <imagename>:<version> myApp

remove service

docker service rm web

get nodes

get the specification of the node

docker node inspect [worker1 | self]

for getting node

docker node ls

Create a stack

when running Docker in swarm mode you can use Docker Stack deploy to deploy a complete application to the swarm deploy accept a type of compose file.

Create Example Application

Voting app For this application we will use the Docker Example Voting App. This app consists of five components:

Python webapp which lets you vote between two options Redis queue which collects new votes .NET worker which consumes votes and stores them in Postgres database backed by a Docker volume Node.js webapp which shows the results of the voting in real time.

create docker-stack.yml

version: "3"
services:
  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]
  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - 5000:80
    networks:
      - frontend
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - 5001:80
    networks:
      - backend
    depends_on:
      - db
    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 1
      labels: [APP=VOTING]
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 120s
      placement:
        constraints: [node.role == manager]
  visualizer:
    image: manomarks/visualizer
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
networks:
  frontend:
  backend:
volumes:
  db-data:

create stack

docker stack deploy --compose-file docker-stack.yml vote

create Dockerfile in compose

version: '3'
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1

Create docker registry

you can get it from docker hub

docker run -d -p 50000:5000 --restart always --name my-registry registry:latest

for send register to our registry we should tag it and push it to the registry

docker tag app:latest my-registry:50000/app:latest
docker push my-registry:50000/app

in the browser you can see it http://localhost:50000/v2/_catalog

when you want to use it you should add the address in insecure

/etc/docker/daemon.json

{
    "insecure-registries" : [ "hostname.cloudapp.net:5000" ]
}

reload docker

sudo systemctl daemon-reload
sudo systemctl restart docker

Cheat sheet

Docker build

docker build [options] . -t "app/container_name"    # name

Docker run

docker run [options] IMAGE  # see `docker create` for options

example

docker run -it --name=myname myappImage 
-it interactive -d detached
-p 8080:8080

Create continer from image

docker create [options] IMAGE
  -a, --attach               # attach stdout/err
  -i, --interactive          # attach stdin (interactive)
  -t, --tty                  # pseudo-tty
      --name NAME            # name your image
  -p, --publish 5000:5000    # port map
      --expose 5432          # expose a port to linked containers
  -P, --publish-all          # publish all ports
      --link container:alias # linking
  -v, --volume `pwd`:/app    # mount (absolute paths needed)
  -e, --env NAME=hello       # env vars

example

 docker create --name app_redis_1 \
  --expose 6379 \
  redis:4

Run command in continer

docker exec [options] CONTAINER COMMAND
  -d, --detach        # run in background
  -i, --interactive   # stdin
  -t, --tty           # interactive

example

 docker exec app_web_1 tail logs/development.log
 docker exec -t -i app_web_1 rails c 

Docker start/stop contianer

docker start [options] CONTAINER
  -a, --attach        # attach stdout/err
  -i, --interactive   # attach stdin

docker stop [options] CONTAINER

Manage continer

 docker ps
 docker ps -a
 docker kill $ID

Docker images

 docker images # show images

 docker images -a   # also show intermediate
 
 docker rmi b750fe78269d

Refrences