Dockerfile
Dockerfile
定义容器内环境中发生的事情。对网络接口和磁盘驱动器等资源的访问在此环境中进行虚拟化,该环境与系统的其余部分隔离,所以您须要将端口映射到外部世界,并具体说明要“复制”到哪些文件那个环境。可是,在执行此操做以后,您能够预期Dockerfile
在此处定义的应用程序的构建 在其运行的任何位置都会彻底相同。html
Dockerfile
建立一个空目录。将目录(cd
)更改成新目录,建立一个名为的文件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"]
这Dockerfile
是指咱们还没有建立的几个文件,即 app.py
和requirements.txt
。让咱们建立下一个。python
再建立两个文件,requirements.txt
而后app.py
将它们放在同一个文件夹中Dockerfile
。这完成了咱们的应用程序,您能够看到它很是简单。当上述Dockerfile
被内置到的图像,app.py
而且 requirements.txt
是由于存在Dockerfile
的ADD
命令,并从输出app.py
是经过HTTP得益于访问EXPOSE
命令。web
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)
如今咱们看到pip install -r requirements.txt
为Python安装Flask和Redis库,应用程序打印环境变量NAME
,以及调用的输出socket.gethostname()
。最后,由于Redis没有运行(由于咱们只安装了Python库,而不是Redis自己),咱们应该指望在这里使用它的尝试失败并产生错误消息。redis
注意:在容器内部访问容器ID时,访问主机名称,这相似于正在运行的可执行文件的进程ID。docker
$ ls Dockerfile app.py requirements.txt
如今运行build命令。这会建立一个Docker镜像,使用-t
它来标记,所以它具备友好的名称。shell
docker build -t friendlyhello .
$ docker images REPOSITORY TAG IMAGE ID friendlyhello latest 326387cea398
登陆本地计算机上的Docker公共注册表。数据库
$ docker login
将本地映像与注册表上的存储库相关联的表示法是 username/repository:tag
flask
docker tag image wangshu19930818/friendlyhello:v1
将标记的图像上传到存储库:浏览器
docker pushwangshu19930818/friendlyhello:v1
从如今开始,您可使用docker run
如下命令在任何计算机上使用和运行您的应用程序:
docker run -p 4000:80 wangshu19930818/friendlyhello:v1
在分布式应用程序中,应用程序的不一样部分称为“服务”。
若是想象一个视频共享站点,它可能包括一个用于将应用程序数据存储在数据库中的服务,一个用于在后台进行视频转码的服务。用户上传内容,前端服务等。
服务实际上只是“生产中的容器”。服务只运行一个映像,但它编码了映像的运行方式 - 它应该使用哪些端口,应该运行多少个容器副本,以便服务具备所需的容量,以及等等。
扩展服务会更改运行该软件的容器实例的数量,从而为流程中的服务分配更多计算资源。
使用Docker平台定义,运行和扩展服务很是容易 - 只需编写一个docker-compose.yml
文件便可。
docker-compose.yml
档案一个docker-compose.yml
文件是一个YAML文件,它定义了如何Docker容器在生产中应表现。
docker-compose.yml
将此文件保存为docker-compose.yml
您想要的任何位置。
version: "3" services: web: # replace username/repo:tag with your name and image details image: wangshu19930818/friendlyhello:v1 deploy: replicas: 5 resources: limits: cpus: "0.1" memory: 50M restart_policy: condition: on-failure ports: - "4000:80" networks: - webnet networks: webnet:
该docker-compose.yml
文件告诉Docker执行如下操做:
拉上传的图像从注册表。
将该映像的5个实例做为一个被调用的服务运行web
,限制每一个实例使用,最多10%的CPU(跨全部内核)和50MB的RAM。
若是一个失败,当即重启容器。
将主机上的端口4000映射到web
端口80。
指示web
容器经过称为负载平衡的网络共享端口80 webnet
。(在内部,容器自己web
在短暂的端口发布到 80端口。)
webnet
使用默认设置(负载平衡的覆盖网络)定义网络。
在咱们docker stack deploy
首先运行命令以前:
docker swarm init
注意:若是您没有运行,docker swarm init
则会收到“此节点不是群集管理器”的错误。
docker stack deploy -c docker-compose.yml getstartedlab
咱们的单个服务堆栈在一台主机上运行已部署映像的5个容器实例。
在咱们的应用程序中获取一项服务的服务ID:
docker ps
列出服务任务:
docker service ps getstartedlab_web
若是您只列出系统上的全部容器,则任务也会显示,但不会被服务过滤:
docker ps -q
curl -4 http://localhost:4000
连续屡次运行,或者在浏览器中转到该URL并点击刷新几回。
能够经过更改replicas
值docker-compose.yml
,保存更改并从新运行docker stack deploy
命令来扩展应用程序:
docker stack deploy -c docker-compose.yml getstartedlab
Docker执行就地更新,无需首先拆除堆栈或杀死任何容器。
如今,从新运行docker ps -q
以查看已从新配置的已部署实例。
若是放大副本,则会启动更多任务,从而启动更多容器。
将应用程序删除docker stack rm
:
docker stack rm getstartedlab
取下群。
docker swarm leave --force