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