欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Docker入门:边玩边学

程序员文章站 2022-06-11 22:08:55
...

Docker概念

Docker是开发人员和系统管理员使用容器开发,部署和运行应用程序的平台。使用Linux容器部署应用程序称为容器化。容器不是新的,但它们用于轻松部署应用程序。
容器化越来越受欢迎,因为容器是:

  • 灵活:即使是最复杂的应用也可以集装箱化。
  • 轻量级:容器利用并共享主机内核。
  • 可互换:你可以即时部署更新和升级。
  • 便携式:你可以在本地构建,部署到云,并在任何地方运行。
  • 可扩展:你可以增加并自动分发容器副本。
  • 可堆叠:你可以垂直和即时堆叠服务。

Docker Image(图像/镜像)

通过运行Docker Image(图像/镜像)启动容器。一个图像是一个可执行的包,其中包括运行应用程序所需的所有内容的代码,运行时的库,环境变量,和配置文件。

容器和虚拟机

一个容器中运行原生Linux和共享主机与其它容器的内核。它运行一个独立的进程,不占用任何其他可执行文件的内存,使其轻量级。

相比之下,虚拟机(VM)运行一个完整的“客户”操作系统,通过虚拟机管理程序对主机资源进行虚拟访问。通常,VM提供的环境比大多数应用程序需要的资源更多。

Dockerfile

Dockerfile主要用来构建图像。它定义了容器内环境中发生的事情。对网络接口和磁盘驱动器等资源的访问在此环境中进行虚拟化,该环境与系统的其他部分隔离。
一般的,Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

安装和检查

Ubuntu 16.04系统上面使用如下命令安装并且把当前用户加入docker用户组,这样就不需要每次运行docker命令都输入sudo

$ sudo apt-get install docker.io
$ sudo usermod -aG docker $USER

重新退出和登录当前用户后,接下来可以使用如下命令简单的检查docker正常运作:

## Display Docker version and info
docker version
docker info

## Execute Docker image
docker run hello-world

## List Docker images
docker images

## List Docker containers (running, all, all in quiet mode)
docker ps
docker ps -a
docker ps -aq

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
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"]

再创建两个文件:requirements.txtapp.py,将它们放在Dockerfile同一个文件夹中。这完成了我们的应用程序,可以看到它非常简单。上述Dockerfile被内置到图像,app.pyrequirements.txt是因为DockerfileCOPY命令而存在,得益于EXPOSE命令,我们可以通过HTTP访问该端口。
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.txtPython安装FlaskRedis库,应用程序打印环境变量NAME,以及socket.gethostname()的输出。最后,因为Redis没有运行(因为我们只安装了Python库,而不是Redis本身),我们应该期望在这里看到尝试失败并产生错误消息。

构建应用程序

我们准备构建应用程序。确保你仍处于新目录的顶层。这是ls应该显示的内容:

$ ls
Dockerfile		app.py			requirements.txt

现在运行build命令。这将创建一个Docker镜像,我们将使用该–tag选项命名(或者-t)

docker build --tag=friendlyhello .

构建好的图像在机器的本地Docker镜像注册表中:

$ docker images
REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

运行应用程序:

运行应用程序,使用以下方法将计算机的端口4000映射到容器的已发布端口80:

docker run -p 4000:80 friendlyhello

这时可以在Web浏览器中转到该URL http://localhost:4000以查看在网页上提供的显示内容。

现在让我们在后台以分离模式运行应用程序:

docker run -d -p 4000:80 friendlyhello

这里获得应用程序的容器ID,然后被踢回终端。容器正在后台运行,通过如下命令可以查看:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED
1fa4ab2cf395        friendlyhello       "python app.py"     28 seconds ago

最后可以使用如下命令来结束这个过程:

docker stop 1fa4ab2cf395

删除图像和容器

使用如下命令可以删除图像和容器:

docker rm <hash>        # Remove specified container from this machine
docker rm $(docker ps -a -q)         # Remove all containers
docker rmi <image id>            # Remove specified image from this machine
docker rmi $(docker images -a -q)   # Remove all images from this machine

Dockerfile常用指令

Dockerfile里面最重要的就是指令部分,指令的一般格式为 INSTRUCTION arguments ,指令包括 FROM 、 MAINTAINER 、 RUN 等。下面是一些常用指令的简单介绍:

FROM

格式为 FROM <image>FROM <image>:<tag>
第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM指令(每个镜像一次)

RUN

格式为 RUN <command>RUN [“executable”, “param1”, “param2”]

前者将在 shell 终端中运行命令,即 /bin/sh -c ;后者则使用 exec 执行。指定使用其它终端可以通过第二种方式实现,例如 RUN [“/bin/bash”, “-c”, “echo hello”]

CMD

支持三种格式

  • CMD [“executable”,”param1″,”param2″] 使用 exec 执行;
  • CMD command param1 param2/bin/sh 中执行;
  • CMD [“param1″,”param2”] 提供给 ENTRYPOINT 的默认参数;

指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

EXPOSE

告诉 Docker 服务端容器暴露的端口号,供互联系统使用。在启动容器时需要通过-PDocker 主机会自动分配一个端口转发到指定的端口。

ENV

格式为 ENV <key> <value> 。 指定一个环境变量,可以被后续 RUN 指令使用,并在容器运行时保持。

ADD

格式为 ADD <src> <dest>
该命令将复制指定的 <src> 到容器中的 <dest> 。 其中 <src> 可以是Dockerfile所在目录的一个相对路径;也可以是一个URL,还可以是一个 tar 文件(自动解压为目录)。

COPY

格式为 COPY <src> <dest>
复制本地主机的 <src> (为 Dockerfile 所在目录的相对路径)到容器中的 <dest>

ENTRYPOINT

两种格式:

  • ENTRYPOINT [“executable”, “param1”, “param2”]
  • ENTRYPOINT command param1 param2

配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖。每个 Dockerfile 中只能有一个 ENTRYPOINT ,当指定多个时,只有最后一个起效。

VOLUME

格式为 VOLUME [“/data”]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等。

WORKDIR

格式为 WORKDIR /path/to/workdir
为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。

ONBUILD

格式为 ONBUILD [INSTRUCTION]
配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。