技术文章

Docker 入门(一)

2019-07-26  本文已影响0人  __笙歌4J

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

  1. 运行docker --version,显示docker版本:
docker --version

Docker version 17.12.0-ce, build c97c6d6
  1. 运行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

  1. 确认您的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.
...

\color{#FF0000}{注意:国内由于众所周知的原因,下载不会成功,你需要开启代理}

  1. 列出下载到您的机器上的hello-world映像:
docker image ls
  1. 列出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页面上提供的显示内容。

image.png

注意:如果您在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
上一篇下一篇

猜你喜欢

热点阅读