沉淀,再出发:Docker的功能浅析
沉淀,再出发:Docker的功能浅析
一、前言
这段时间一直在使用docker,发现docker的技术有很多,从最开始的将自己的程序打包成docker中的镜像,然后上传和下载镜像并使用,再到后来的在集群之中使用docker来运行自己的任务,使用swarm,docker-machine,dockerfile,yaml等技术和工具来完成docker对任务的管理,可以说学习docker有着很大的作用和意义,使用docker的容器,镜像机制,将所有的依赖使用文件来管理,很轻松的进行打包上传和下载,大大的节省了布置环境需要的时间和精力,这种思想非常的棒,可以说是轻量级的虚拟机。
二、Docker功能
我们从一个例子开始,一步步的认识docker。实验环境是使用Linux的Ubuntu16.04真机环境或者虚拟机环境。
2.1、下载和安装docker
这个我们已经探讨过了,大家可以查看我的文章。
2.2、测试是否安装成功
1 docker --version
至此可以看到docker已经安装成功了,其他的查看命令如下:
## List Docker CLI commands docker docker container --help ## Display Docker version and info docker --version docker version docker info ## Execute Docker image docker run hello-world ## List Docker images docker image ls ## List Docker containers (running, all, all in quiet mode) docker container ls docker container ls --all docker container ls -aq
2.3、容器的概念和使用(Dockerfile)
我们使用dockerfile文件来定义一个容器运行所需的环境,比如一些包依赖,环境变量配置等等,之后就可以放心的进行自己程序的开发而不需要自己配置了。
首先我们创建一个新的文件夹,然后在该文件夹中创建一个名为Dockerfile的文件,在文件中作如下操作:
Dockerfile:
# Use an official Python runtime as a parent image FROM python:2.7-slim # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /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"]
在创建上述文件提到的两个文件:
requirements.txt:
Flask
Redis
app.py:
1 from flask import Flask 2 from redis import Redis, RedisError 3 import os 4 import socket 5 6 # Connect to Redis 7 redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) 8 9 app = Flask(__name__) 10 11 @app.route("/") 12 def hello(): 13 try: 14 visits = redis.incr("counter") 15 except RedisError: 16 visits = "<i>cannot connect to Redis, counter disabled</i>" 17 18 html = "<h3>Hello {name}!</h3>" \ 19 "<b>Hostname:</b> {hostname}<br/>" \ 20 "<b>Visits:</b> {visits}" 21 return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) 22 23 if __name__ == "__main__": 24 app.run(host='0.0.0.0', port=80)
具体过程如下所示:
然后我们运行该Dockerfile文件,使用如下命令,其中friendlyhello 为我们给我们的容器起的名字。之后docker就会自动按照Dockerfile上面的指令一步步的下载我们需要的环境并进行配置。
1 docker build -t friendlyhello .
最终配置成功,生成了我们需要的容器,并且我们可以运行这个容器,通过网页或者curl命令来访问可以发现程序已经可以工作了。
docker run -p 4000:80 friendlyhello
同样的我们可以使用如下命令来停止该容器产生的镜像的运行:
docker container stop 容器id
这样我们完成了第一步,之后我们需要将这个镜像存到自己的仓库之中,并且上传到注册中心之中,使用tag命令,我们将该镜像进行标记,注意这里还没有上传,注意后面的“用户名/仓库:标记”我们最好这样做,首先用户名就是我们注册的docker的账户id,仓库和标记这个我们可以自己填写,在自己的注册中心会生成这个东西,也可以使用现有的。
docker tag image的名称 username/repository:tag
可以看到标记成功,然后我们上传到自己的注册中心之中,在这里如果大家没有注册docker账户的,是不能完成下面操作的,因此需要先注册账户,但是docker在注册的时候需要使用Google的服务,也就是要访问www.google.com这个服务,势必需要外网来操作,如果大家没有外网,那就没办法了,这点也看出来当初Google的离开真是程序员的一大损失呀。不过大家可以通过代理等方式来FQ,并且只是注册的时候需要外网,之后上传和下载是不需要的,因此,可以借用别人的外网来注册。
下面是我注册并进行上传的内容,非常的方便。
下面我们上传:
docker push username/repository:tag
至此,我们已经上传成功了,并且可以在其他的电脑上下载并且使用了,就好像我们开始使用hello-world一样,不需要任何的配置。我们在任何的机器上(安装有docker)使用如下命令就可以自动下载并运行了。
docker run -p 4000:80 username/repository:tag
常用的命令如下:
1 docker build -t friendlyhello . # Create image using this directory's Dockerfile 2 docker run -p 4000:80 friendlyhello # Run "friendlyname" mapping port 4000 to 80 3 docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode 4 docker container ls # List all running containers 5 docker container ls -a # List all containers, even those not running 6 docker container stop <hash> # Gracefully stop the specified container 7 docker container kill <hash> # Force shutdown of the specified container 8 docker container rm <hash> # Remove specified container from this machine 9 docker container rm $(docker container ls -a -q) # Remove all containers 10 docker image ls -a # List all images on this machine 11 docker image rm <image id> # Remove specified image from this machine 12 docker image rm $(docker image ls -a -q) # Remove all images from this machine 13 docker login # Log in this CLI session using your Docker credentials 14 docker tag <image> username/repository:tag # Tag <image> for upload to registry 15 docker push username/repository:tag # Upload tagged image to registry 16 docker run username/repository:tag # Run image from a registry
2.4、服务的概念和应用
我们首先需要安装 Docker Compose,安装方法如下:注意版本号如果已经过期或者不能访问我们进入相应的网站查找能用的版本并进行更改。
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
Services are really just “containers in production.” A service only runs one image, but it codifies the way that image runs—what ports it should use, how many replicas of the container should run so the service has the capacity it needs, and so on. Scaling a service changes the number of container instances running that piece of software, assigning more computing resources to the service in the process.
使用docker-compose.yml文件可以很轻松的定义服务:
1 version: "3" 2 services: 3 web: 4 # replace username/repo:tag with your name and image details 5 image: username/repo:tag 6 deploy: 7 replicas: 5 8 resources: 9 limits: 10 cpus: "0.1" 11 memory: 50M 12 restart_policy: 13 condition: on-failure 14 ports: 15 - "4000:80" 16 networks: 17 - webnet 18 networks: 19 webnet:
之后运行如下命令来初始化当前节点为管理节点:
docker swarm init
docker stack deploy -c docker-compose.yml getstartedlab(自己定义的程序名称)
然后我们可以查看相应的服务,Look for output for the web service, prepended with your app name. If you named it the same as shown in this example, the name is getstartedlab_web. The service ID is listed as well, along with the number of replicas, image name, and exposed ports.
docker service ls
docker service ps getstartedlab_web
可以看到我们的容器生成的镜像已经可以运行了,并且根据上述的yaml文件,生成了五个镜像,在相应的内存空间之内进行运行,这就是服务的概念。如果我们以后打算对服务的参数进行更改我们可以编辑上述的yaml文件,然后重新运行docker stack deploy ....命令即可。
同理,我们可以移除掉我们创建的stack和swarm:
#Take the app down with docker stack rm: docker stack rm getstartedlab #Take down the swarm. docker swarm leave --force
1 docker stack ls # List stacks or apps 2 docker stack deploy -c <composefile> <appname> # Run the specified Compose file 3 docker service ls # List running services associated with an app 4 docker service ps <service> # List tasks associated with an app 5 docker inspect <task or container> # Inspect task or container 6 docker container ls -q # List container IDs 7 docker stack rm <appname> # Tear down an application 8 docker swarm leave --force # Take down a single node swarm from the manager
2.5、swarm
从上面的例子我们其实可以看出swarm是干什么用的了,其实就是在多个机器上面进行任务的分配、通信、信息的交互的一个软件,服务的概念也是在这样的集群上面才有意义的,因此,将swarm和服务结合起来就能实现真正意义上的生产环境了。
我们需要先安装docker-machine:
base=https://github.com/docker/machine/releases/download/v0.15.0 && curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine
然后使用如下命令创建两个虚拟机,因为我们是使用virtualbox创建的,所以需要先下载virtualbox,之后进行创建:
docker-machine create --driver virtualbox myvm1
docker-machine create --driver virtualbox myvm2
docker-machine ls
docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
docker-machine ssh myvm2 "docker swarm join \ --token <token> \ <ip>:2377"
docker-machine ssh myvm1 "docker node ls"
之后的操作,因为时间的原因以后再完成。
1 docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux) 2 docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 # Win10 3 docker-machine env myvm1 # View basic information about your node 4 docker-machine ssh myvm1 "docker node ls" # List the nodes in your swarm 5 docker-machine ssh myvm1 "docker node inspect <node ID>" # Inspect a node 6 docker-machine ssh myvm1 "docker swarm join-token -q worker" # View join token 7 docker-machine ssh myvm1 # Open an SSH session with the VM; type "exit" to end 8 docker node ls # View nodes in swarm (while logged on to manager) 9 docker-machine ssh myvm2 "docker swarm leave" # Make the worker leave the swarm 10 docker-machine ssh myvm1 "docker swarm leave -f" # Make master leave, kill swarm 11 docker-machine ls # list VMs, asterisk shows which VM this shell is talking to 12 docker-machine start myvm1 # Start a VM that is currently not running 13 docker-machine env myvm1 # show environment variables and command for myvm1 14 eval $(docker-machine env myvm1) # Mac command to connect shell to myvm1 15 & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression # Windows command to connect shell to myvm1 16 docker stack deploy -c <file> <app> # Deploy an app; command shell must be set to talk to manager (myvm1), uses local Compose file 17 docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app) 18 docker-machine ssh myvm1 "docker stack deploy -c <file> <app>" # Deploy an app using ssh (you must have first copied the Compose file to myvm1) 19 eval $(docker-machine env -u) # Disconnect shell from VMs, use native docker 20 docker-machine stop $(docker-machine ls -q) # Stop all running VMs 21 docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images
三、总结
学习一门技术,就要理解其中的原理,但是最开始的时候还是要先学会使用,上面的命令大家多多练习是非常有用的。docker还有很多的哲理和原理在其中,学无止境,我们一定要谦虚、认真、坚定。