docker-基本概念

docker是一个让开发者或管理员通过容器来开发,部署,运行应用的平台。使用容器来部署应用被称为容器化。

容器化变得越来越流行是因为容器有以下特性:

  • 灵活:即使很复杂的应用也可以被容器化
  • 轻量:与宿主机共享内核
  • 热更新:应用运行时部署更新和升级
  • 可移植:可以在本地构建,部署到任何地方
  • 可扩展:可以增加并且自动发布容器副本
  • 可堆叠:可以堆叠服务

ImagesContainers

容器通过运行镜像启动。镜像是包含应用运行所需代码,运行时,库,环境变量和配置文件的可执行包。
容器是镜像的运行时实例——当执行的时候镜像加载到内存(也就是有状态的镜像或者用户进程)。可以通过docker ps查看正在运行的容器列表,就像在linux中一样。

ContainersVirtual machines

容器原生的运行在Linux上,并且和其他容器共享宿主及其的内核。它作为一个独立的运行的进程,不占用其他进程的内存,因此很轻量级。

相反,虚拟机运行一个完整的操作系统通过hypervisor虚拟访问主机资源。一般来说,虚拟机提供了多于大部分应用所需的资源环境。

新的开发环境

过去,如果你写一个新的Python应用,第一步是在你的机器上安装Python运行时。并且,创建的环境是应用运行是所期望的,同时也尽可能于正式环境一致。

使用Docker,只需要拿一个可移植的Python运行时作为镜像,不需要安装。然后,构建一个包含基础Python镜像和应用的代码,确保应用的依赖,运行时都在一起。

这些可移植的镜像被DockerFile定义。

使用Dockerfile定义一个容器

Dockerfile定义了你容器中的环境是怎么样的。访问类似网络接口和硬盘驱动被虚拟化进这个环境,这个环境独立于系统的其他部分,所以需要映射端口到外面的世界,并且特别注意你想写进这个环境中的文件。做了这些之后,从Makefile文件中构建的应用无论在什么地方执行都表现出一样的行为。

Dockfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 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
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"]

app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

requirements.txt

1
2
Flask
Redis

根目录结构如下:

1
2
3
4
.
├── app.py
├── Dockerfile
└── requirements.txt

构建app

1
docker build --tag=friendlyhello .

运行app

1
docker run -p 4000:80 friendlyhello

daemon模式运行

1
docker run -d -p 4000:80 friendlyhello

查看container信息

1
docker container ls

停止容器

1
docker container stop container-ID

container相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker build -t friendlyhello .  # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyhello # Run "friendlyhello" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode
docker container ls # List all running containers
docker container ls -a # List all containers, even those not running
docker container stop <hash> # Gracefully stop the specified container
docker container kill <hash> # Force shutdown of the specified container
docker container rm <hash> # Remove specified container from this machine
docker container rm $(docker container ls -a -q) # Remove all containers
docker image ls -a # List all images on this machine
docker image rm <image id> # Remove specified image from this machine
docker image rm $(docker image ls -a -q) # Remove all images from this machine
docker login # Log in this CLI session using your Docker credentials
docker tag <image> username/repository:tag # Tag <image> for upload to registry
docker push username/repository:tag # Upload tagged image to registry
docker run username/repository:tag # Run image from a registry

Services

在分布式应用中,应用的不同部分被成为services。例如,想象一个video分享网站,它可能包含一个存储应用数据到数据库的一个服务,一个在后后台转码用户上传的数据,一个服务在前台等等。

Services就像成产环境中的containers。一个service仅仅运行一个image,但是它决定image如何运行——哪些端口可以使用,服务实现高可用所需要的副本个数等等。扩展一个服务改变运行那个软件所运行容器实例的个数,在进程中赋予更多计算资源给服务。

幸运的是这很容易去定义,执行和扩展services通过Docker平台–仅仅写一个docker-compose.yml文件。

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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: