Docker Learning Process

Keywords: Docker Python Redis ssh

Following is a step-by-step tutorial on learning docker

Common commands:

Delete all containers
docker rm `docker ps -a -q`

View all containers
docker container ls --all

Stop a single container
 docker container stop container id

Remove all mirrors
docker rmi `docker images -q`

Remove a single image
 docker rmi mirror id

A Dockerfile

Docker automatically generates a mirror by reading the instructions in the Dockerfile, which, in my understanding, expresses the entire application environment as it appears, and then Docker generates the final running environment we need from the Dockerfile.

1.1 Create a new directory, then create a Dockerfile, copy and paste the contents

# Use an official Python runtime as a parent image
# This was the official website: FROM python:2.7-slim, but I can't run it. Change to the one below
FROM python:3.6

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

After 1.2, create two more files, requirements.txt and app.py.

requirements.txt

Flask
Redis

app. py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

Viewing the directory should look like this

$ ls
Dockerfile		app.py			requirements.txt

1.3 Creating a docker image

docker build --tag=friendlyhello .

You can use -t

This is the time to view the mirror

$ docker image ls

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

1.4 Running applications

docker run -p 4000:80 friendlyhello

* Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
172.17.0.1 - - [15/Feb/2019 06:41:44] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [15/Feb/2019 06:41:44] "GET /favicon.ico HTTP/1.1" 404 -

The service port generated internally by python is 80, but the message comes from inside the container and can be set to 4000.Access address: http://localhost:4000

You can see that the following interface is generated.CTRL+C Exit Terminal

Running an application in a detached mode in the background is equivalent to running in the background behind the scenes

docker run -d -p 4000:80 friendlyhello

//Return long container id
4f8862d7a00374f52cf51d3dee66ccf3b49f366ce5267a1cc929ce2de8407312

//View Containers
zldeMacBook-Air-5:celery_test zl$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                  NAMES
4f8862d7a003        friendlyhello       "python app.py"     About a minute ago   Up About a minute   0.0.0.0:4000->80/tcp   quizzical_meninsky

//Stop Container
docker container stop  container id

Two Shared Mirrors

2.1 Create a docker id web address: https://hub.docker.com/
2.2 Log on to the local docker

docker login

zldeMacBook-Air-5:celery_test zl$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: #########
Password: 
Login Succeeded

2.3 Marker Mirror

docker tag image username/repository:tag

//Example
zldeMacBook-Air-5:celery_test zl$ docker tag friendlyhello #######/docker-com:part1
zldeMacBook-Air-5:celery_test zl$ docker image ls
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
#########/docker-com   part1               45df9f7a34e3        36 minutes ago      932MB
friendlyhello          latest              45df9f7a34e3        36 minutes ago      932MB
python                 3.6                 e0a418687f6c        2 days ago          922MB

2.4 Release Mirror

docker push username/repository:tag

2.5 Pull and run the mirror from the remote repository

docker run -p 4000:80 username/repository:tag

Wherever the docker run is executed, it extracts your image, along with Python and all dependencies requirements.txt, and runs your code.They all travel together in a neat package and you don't need to install anything on the host to get Docker to run it.

Three docker-compose.yml

3.1 Create docker-compose.yml

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

The docker-compose.yml file tells Docker to do the following:

  • Pull Uploaded Mirror
  • Run the web with the five mirrored instances as invoked services, limiting each instance to a maximum of 10% CPU (across all cores) and 50MB of RAM.
  • If one fails, restart the container immediately.
  • Map port 4000 on the host to web port 80.
  • Indicates that the web container passes through a network shared port 80 webnet called load balancing.(Internally, the container itself web is published to port 80 on a short port.)
  • The webnet defines the network with default settings (load balanced overlay networks).

3.2 Run new load balancing applications

docker swarm init

3.3 Name the application.Here, it is set to getstartedlab:

zldeMacBook-Air-5:celery_test zl$ docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web

3.4 View Services

zldeMacBook-Air-5:celery_test zl$ docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                        PORTS
08zb9um5hp59        getstartedlab_web   replicated          5/5                 284794223/docker-com:part1   *:4000->80/tcp

A single container running in a service is called a task.Tasks are given a unique ID that increases digitally, listing service tasks

zldeMacBook-Air-5:celery_test zl$ docker service ps getstartedlab_web
ID                  NAME                  IMAGE                        NODE                    DESIRED STATE       CURRENT STATE           ERROR               PORTS
l8hmq01l0jap        getstartedlab_web.1   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 2 minutes ago                       
w8ttti8a2yvi        getstartedlab_web.2   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 2 minutes ago                       
qeyugcp87euy        getstartedlab_web.3   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 2 minutes ago                       
o65p8ajedy4q        getstartedlab_web.4   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 2 minutes ago                       
92gd50jd4zv0        getstartedlab_web.5   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 2 minutes ago

List containers, tasks will also be displayed

zldeMacBook-Air-5:celery_test zl$ docker container ls
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS               NAMES
4a524d0c6432        284794223/docker-com:part1   "python app.py"     3 minutes ago       Up 3 minutes        80/tcp              getstartedlab_web.4.o65p8ajedy4q0dwai7eiicjho
b8e953ce46e5        284794223/docker-com:part1   "python app.py"     3 minutes ago       Up 3 minutes        80/tcp              getstartedlab_web.2.w8ttti8a2yvi8dg77pqzcm040
32a6b31905c3        284794223/docker-com:part1   "python app.py"     3 minutes ago       Up 3 minutes        80/tcp              getstartedlab_web.3.qeyugcp87euy0l6g0taaa70ho
6eabe10745db        284794223/docker-com:part1   "python app.py"     3 minutes ago       Up 3 minutes        80/tcp              getstartedlab_web.1.l8hmq01l0japzvgwxj4x3xfje
0b2d7df335ad        284794223/docker-com:part1   "python app.py"     3 minutes ago       Up 3 minutes        80/tcp              getstartedlab_web.5.92gd50jd4zv07c2yxml613nmx

open http://localhost:4000 , refresh a few more times, cycle refresh according to task id

View application name

zldeMacBook-Air-5:celery_test zl$ docker stack ps getstartedlab
ID                  NAME                  IMAGE                        NODE                    DESIRED STATE       CURRENT STATE            ERROR               PORTS
l8hmq01l0jap        getstartedlab_web.1   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 10 minutes ago                       
w8ttti8a2yvi        getstartedlab_web.2   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 10 minutes ago                       
qeyugcp87euy        getstartedlab_web.3   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 10 minutes ago                       
o65p8ajedy4q        getstartedlab_web.4   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 10 minutes ago                       
92gd50jd4zv0        getstartedlab_web.5   284794223/docker-com:part1   linuxkit-025000000001   Running             Running 10 minutes ago 

3.5 If you modify the contents of docker-compose.yml, re deploy it directly

docker stack deploy -c docker-compose.yml getstartedlab

Docker performs in-place updates without first removing the stack or killing any containers.

Close the application
docker stack rm getstartedlab

Close the group
docker swarm leave --force

Four Clusters Swarms

4.1 Installation VirtualBox
4.2 docker-machine uses the VirtualBox driver to create several VM s (virtual machines)

docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2

//View virtual machine ip address
$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.100:2376           v17.06.2-ce
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v17.06.2-ce

//Restart Virtual Machine
docker-machine start myvm1

4.3 Initialize SWARM and add nodes
The first machine acts as a manager, it executes management commands and verifies that workers join the group, the second is workers

docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"

//For example:
zldeMacBook-Air-5:celery_test zl$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.100:2377"
Swarm initialized: current node (27hhgfhiapmblns92bdq1lrw2) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-5rkujt8zszmcys6u6i9rtrbr4q6g3k1376illqcwun0ayned95-2iu0aiurmi6v845cjxh0pvtxl 192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

2377 is the cluster management port.docker-machine ssh joins the new group as a worker with myvm2

$ docker-machine ssh myvm2 "docker swarm join --token <token> <ip>:2377"

zldeMacBook-Air-5:celery_test zl$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-5rkujt8zszmcys6u6i9rtrbr4q6g3k1376illqcwun0ayned95-2iu0aiurmi6v845cjxh0pvtxl 192.168.99.100:2377"
This node joined a swarm as a worker.

This has created the first group to view the nodes in this group

zldeMacBook-Air-5:celery_test zl$ docker-machine ssh myvm1 "docker node ls"
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
27hhgfhiapmblns92bdq1lrw2 *   myvm1               Ready               Active              Leader              18.09.2
mpt3sba1mefhue6krgeffg7hp     myvm2               Ready               Active                                  18.09.2

4.4 Deploy your application on a cluster

zldeMacBook-Air-5:celery_test zl$ docker-machine env myvm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/zl/.docker/machine/machines/myvm1"
export DOCKER_MACHINE_NAME="myvm1"
# Run this command to configure your shell: 
# eval $(docker-machine env myvm1)
Run the given command to configure the shell
zldeMacBook-Air-5:celery_test zl$ eval $(docker-machine env myvm1)
zldeMacBook-Air-5:celery_test zl$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
myvm1   *        virtualbox   Running   tcp://192.168.99.100:2376           v18.09.2   
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.09.2   

4.5 Deploying applications on swarm Manager

docker stack deploy -c docker-compose.yml getstartedlab

The application is deployed in a cluster!

zldeMacBook-Air-5:celery_test zl$ docker stack ps getstartedlab
ID                  NAME                  IMAGE                        NODE                DESIRED STATE       CURRENT STATE              ERROR               PORTS
zncq2tfprafa        getstartedlab_web.1   284794223/docker-com:part1   myvm2               Running             Preparing 51 seconds ago                       
mh7khank14f0        getstartedlab_web.2   284794223/docker-com:part1   myvm1               Running             Preparing 51 seconds ago                       
ufo2rv5gr9gs        getstartedlab_web.3   284794223/docker-com:part1   myvm2               Running             Preparing 51 seconds ago                       
kp4rud24d8xb        getstartedlab_web.4   284794223/docker-com:part1   myvm1               Running             Preparing 51 seconds ago                       
nun4umxcayfz        getstartedlab_web.5   284794223/docker-com:part1   myvm2               Running             Preparing 51 seconds ago  

Access Cluster http://192.168.99.101:4000/ perhaps http://192.168.99.100:4000/

Clean up applications
docker-machine ssh myvm1 "docker stack rm getstartedlab"

If you want to detach the work node from the swarm cluster
docker-machine ssh myvm2 "docker swarm leave"

If management node is closed
docker-machine ssh myvm1 "docker swarm leave --force"

Five Stacks

5.1 Redeploy the yml file and restart

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: 284794223/docker-com:part1
    deploy:
      replicas: 5
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ports:
      - "80:80"
    networks:
      - webnet
  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet
networks:
  webnet:
restart
zldeMacBook-Air-5:celery_test zl$ docker stack deploy -c docker-compose.yml getstartedlab
Updating service getstartedlab_web (id: y2nju7rfxtjmyn8zj1138wd02)
Creating service getstartedlab_visualizer

Visit visualizer: http://192.168.99.101:8080/ You can see that all services are on top
Next, add the redis service and modify the conpose file

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      restart_policy:
        condition: on-failure
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
    ports:
      - "80:80"
    networks:
      - webnet
  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]
    networks:
      - webnet
  redis:
    image: redis
    ports:
      - "6379:6379"
    volumes:
      - "/home/docker/data:/data"
    deploy:
      placement:
        constraints: [node.role == manager]
    command: redis-server --appendonly yes
    networks:
      - webnet
networks:
  webnet:

Create a directory to store data and redeploy it

appledeMacBook-Air-92:celery_test zl$ docker-machine ssh myvm1 "mkdir ./data"
appledeMacBook-Air-92:celery_test zl$ docker stack deploy -c docker-compose.yml getstartedlab
Creating service getstartedlab_redis
Updating service getstartedlab_web (id: sjjsaahnixwrnlu6sp1tu8n3v)
Updating service getstartedlab_visualizer (id: xiwmyngfvxj828fahszzcaa7g)

Visit: http://192.168.99.102/ You can see that Visits has changed
Visit: http://192.168.99.101:8080/ You can see one more redis service

Posted by seriousdamage on Sun, 28 Apr 2019 08:30:38 -0700