1.Docker 简介
Docker是一个供开发人员和系统管理员使用容器开发、部署和运行应用程序的平台。使用Linux容器部署应用程序称为容器化。容器并不新鲜,但是它们用于轻松部署应用程序却很新鲜。
Docker 之所以受欢迎主要是因为它有以下特点:
- 灵活性: 即使是最复杂的应用程序也可以被封装。
- 轻量级:容器利用并共享主机内核。
- 可替换: 您可以实时部署更新和升级。
- 可移植性:您可以在本地构建、部署到云,并在任何地方运行。
- 可伸缩: 您可以增加并自动分发容器副本。
- 可堆叠: 您可以垂直地、动态地堆叠服务。
Images & containers (镜像与容器)
通过运行镜像启动容器。镜像是一个可执行包,包含运行应用程序所需的所有内容——代码、运行时、库、环境变量和配置文件。
容器是镜像的运行时实例——当执行镜像时,镜像在内存中会变成什么(即带有状态的镜像或用户进程)。您可以使用docker ps
命令看到正在运行的容器列表,就像在Linux中一样。
Containers & virtual machines(容器与虚拟机)
容器在Linux上本地运行,并与其他容器共享主机的内核。它运行一个离散的进程,不占用比任何其他可执行程序更多的内存,使其轻量级。
相反,虚拟机(VM)运行一个成熟的“客户”操作系统,通过管理程序对主机资源进行虚拟访问。一般来说,vm提供的环境提供的资源比大多数应用程序所需的资源要多。
容器结构 | VM结构 |
---|
2.准备Docker环境
win10_or Mac :https://www.docker.com/products/docker-desktop
Mac 命令行安装: brew cask install docker
Ubuntu: wget -qO- https://get.docker.com/ | sh
CentOS:
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum makecache fast
sudo yum -y install docker-ce
sudo systemctl start docker
3. Test Docker version
- 运行
docker --version
,显示docker版本:
docker --version
Docker version 17.12.0-ce, build c97c6d6
- 运行
docker info
(或docker version
)查看更多关于docker安装的细节:
docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 17.12.0-ce
Storage Driver: overlay2
...
为了避免权限错误(请使用 sudo
),将用户添加到docker组。
4. Test Docker installation
- 确认您的Docker 正常运行,安装一个简单的镜像 hello-world:
docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ca4f61b1923c: Pull complete
Digest: sha256:ca0eeb6fb05351dfc8759c20733c91def84cb8007aa89a5bf606bc8b315b9fc7
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
- 列出下载到您的机器上的hello-world映像:
docker image ls
- 列出hello-world容器(由图像生成),该容器在显示其消息后退出。如果它还在运行,您就不需
--all
选项:
docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS
54f4984ed6a8 hello-world "/hello" 20 seconds ago Exited (0) 19 seconds ago
命令清单:
## 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
5.使用Dockerfile 定义容器
Dockerfile定义容器内的环境的具体信息。对网络接口和磁盘驱动器等资源的访问是在此环境中虚拟化的,该环境与系统的其他部分是隔离的,因此需要将端口映射到外部世界,并指定要将哪些文件“复制”到该环境。但是,在这样做之后,您可以期望在这个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
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"]
这个Dockerfile引用了两个我们还没有创建的文件,即app.py和requirements.txt。接下来创建他们。
应用程序本身
创建另外两个文件requirements.txt和app.py,并将它们与Dockerfile放在同一个文件夹中。这就完成了我们的应用程序,正如您所看到的,它非常简单。当将上面的Dockerfile构建到一个映像中时,由于Dockerfile的COPY命令,出现了app.py和requirements.txt,并且由于EXPOSE命令,可以通过HTTP访问来自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)
现在我们看到pip install -r requirement .txt安装了用于Python的Flask和Redis库,应用程序打印环境变量名以及对socket.gethostname()的调用的输出。最后,因为Redis没有运行(因为我们只安装了Python库,而没有安装Redis本身),所以我们应该预期在这里使用它的尝试会失败并产生错误消息。
注意:在容器中检索容器ID时访问主机名,这与正在运行的可执行文件的进程ID类似。
就是这样!您的系统上不需要Python或requirements.txt中的任何东西,构建或运行此映像也不需要在系统上安装它们。看起来您并没有真正使用Python和Flask建立一个环境,但是您已经这样做了。
构建应用程序
我们已经准备好构建应用程序。请确保您仍然位于新目录的顶层。下面是ls应该显示的内容:
$ ls
Dockerfile app.py requirements.txt
现在运行build命令。这将创建一个Docker镜像,我们将使用--tag
选项为其命名。如果您想使用较短的选项,请使用-t
。
docker build --tag=friendlyhello .
你建立的镜像在哪里?它在你的机器的本地Docker镜像注册表:
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
注意标签是如何默认为 latest
的。tag选项的完整语法应该类似于--tag=friendlyhello:v0.0.1
.
Linux用户的故障排除
代理服务器设置
一旦web应用程序启动并运行,代理服务器就会阻塞到它的连接。如果您在代理服务器的后面,使用ENV
命令指定代理服务器的主机和端口,将以下行添加到Dockerfile中:# Set proxy server, replace host:port with values for your servers ENV http_proxy host:port ENV https_proxy host:port
DNS设置
DNS错误配置可能导致pip出现问题。您需要设置自己的DNS服务器地址,以使pip正常工作。您可能希望更改Docker守护进程的DNS设置。您可以在/etc/docker/daemon.上编辑(或创建)配置文件json与dns密钥,如下:{ "dns": ["your_dns_address", "8.8.8.8"] }
在上面的例子中,列表的第一个元素是DNS服务器的地址。第二项是谷歌的DNS,当第一个DNS不可用时可以使用它。
在继续之前,保存daemon.json
。然后重启docker服务。sudo service docker restart
修复后,重试运行
build
命令。
运行应用程序
运行应用程序,使用-p
将机器的端口4000映射到容器的已发布端口80:
docker run -p 4000:80 friendlyhello
您应该会看到一条消息,说明Python正在http://0.0.0.0:80为您的应用程序提供服务。但是该消息来自容器内部,它不知道您将该容器的80端口映射到4000,从而生成正确的URL http://localhost:4000。
转到web浏览器中的URL,查看web页面上提供的显示内容。
注意:如果您在Windows 7上使用Docker工具箱,请使用Docker机器IP而不是localhost。例如,http://192.168.99.100:4000。要查找IP地址,请使用命令docker-machine IP。
您还可以使用shell中的curl命令查看相同的内容。
$ curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
这个端口映射为4000:80,演示了Dockerfile中的 EXPOSE
与运行 docker run -p
时设置的发布值之间的差异。在后面的步骤中,将主机上的端口4000映射到容器中的端口80,并使用http://localhost。
在终端中按CTRL+C
退出。
在Windows上,显式地停止容器
在Windows系统上,CTRL+C
不会停止容器。因此,首先键入CTRL+C
来返回提示符(或打开另一个shell),然后键入docker container ls
来列出正在运行的容器,然后键入docker container stop < container NAME或ID>
来停止容器。否则,当您尝试在下一步中重新运行容器时,守护进程将发出错误响应。
现在让我们在后台以分离模式运行应用程序:
docker run -d -p 4000:80 friendlyhello
你获得应用程序的长容器ID,然后被踢回终端。您的容器仍在后台运行。您还可以通过docker container ls
命令看到带有容器ID缩写(ID与缩写ID两者在运行命令时可以互换工作):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
注意,CONTAINER ID
匹配 http://localhost:4000
上的内容。
现在使用docker container stop
结束进程,使用CONTAINER ID
,如下所示:
docker container stop 1fa4ab2cf395
网友评论