运用 Distroless 镜像来保护 Kubernetes 上的容器。
容器改动了我们看待技术基础设备的方式。这是我们运转运用顺序方式的一次庞大飞跃。容器编排和云效劳一同为我们提供了一种近乎有限规模的无缝扩展才能。
依据定义,容器应该包含 「运用顺序」 及其 「运转时依赖项」。但是,在理想中,它们包含的远不止这些。标准容器基础映像包含标准 Linux 发行版中可以找到的包管理器、shell 和其他顺序。
虽然这些都是构建容器镜像所必需的,但它们不应该成为最终镜像的一部分。例如,一旦你把包安装好了,就不再需求在容器中运用 apt 等包管理工具了。
这不只使你的容器里充溢了不必要的软件包和顺序,而且还为网络罪犯提供了攻击特定顺序破绽的时机。
你应该一直了解容器运转时中存在什么,并且应该准确地限制其只包含运用顺序所需的依赖项。
除了那些必要的,你不应该安装任何东西。一些抢先的科技巨头,如谷歌,有多年在消费中运转容器的阅历,曾经采用了这种办法。
谷歌如今经过提供 Distroless 镜像向全世界开放这种才能。谷歌构建的这些镜像的目的是只包含你的运用顺序及其依赖项,同时它们将没有常规 Linux 发行版的一切特性,包括 shell。
「这意味着虽然可以像以前一样运转运用顺序的容器,但不能在容器运转的时分进入容器内」。这是一个严重的安全改良,由于你如今曾经为黑客经过 shell 进入你的容器翻开了大门。
Distroless 基础镜像谷歌为大少数盛行的编程言语战争台提供了 Distroless 的基础镜像。
以下基础镜像是正式发布的版本:
gcr.io/distroless/static-debian10
gcr.io/distroless/base-debian10
gcr.io/distroless/java-debian10
gcr.io/distroless/cc-debian10
gcr.io/distroless/nodejs-debian10
下面的基础镜像仍在实验阶段,不引荐用于消费环境:
gcr.io/distroless/python2.7-debian10
gcr.io/distroless/python3-debian10
gcr.io/distroless/java/jetty-debian10
gcr.io/distroless/dotnet
构建 Distroless 镜像谷歌在外部运用 Bazel 来构建容器映像,但是我们可以运用 Docker 来做异样的事情。关于运用 Distroless 镜像的一个有争议的成绩是:当我们有一个 Distroless 镜像时,我们如何运用 Dockerfile 来构建我们的运用顺序呢?
通常,Dockerfile 以一个标准的 OS 基础镜像末尾,然后是创立适当的运转时构建所需执行的多个步骤。这包括包的安装,为此需求像 apt 或 yum 这样的包管理器。
有两种办法:
先在 Docker 外部构建好你的运用顺序,然后运用 Dockerfile 中的 ADD 或 COPY 指令将二进制包复制到容器中。
运用多阶段 Docker 构建。这是 Docker 17.05 及以后版本的一个新特性,它允许你将构建分为不同的阶段。第一阶段可以从标准的 OS 基础镜像末尾,可以协助你构建运用顺序;第二阶段可以复杂地从第一阶段获取构建的文件并运用 Distroless 作为基础镜像。
为了了解它是如何任务的,让我们运用多阶段构建流程停止一个实践操作练习。
必要条件你需求具有以下内容:
Docker 版本大于等于 17.05,用于构建镜像
可选的 Kubernetes 集群用于实际练习的第二部分。假设你想在 Docker 中运转你的容器,你可以运用等价的 docker 命令。
GitHub 代码仓作为实际练习,将 此代码仓 Fork 到你的 GitHub 帐号下,然后克隆 GitHub 代码仓并运用 cd 进入到项目目录下。
该代码仓包含一个 Python 的 Flask 运用顺序,当你调用API时,该运用顺序会照应 Hello World!。
app.py 文件如下所示:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Dockerfile 包含两个阶段:
FROM python:2.7-slim AS build
ADD . /app
WORKDIR /app
RUN pip install --upgrade pip
RUN pip install -r ./requirements.txt
FROM gcr.io/distroless/python2.7
COPY --from=build /app /app
COPY --from=build /usr/local/lib/python2.7/site-packages /usr/local/lib/python2.7/site-packages
WORKDIR /app
ENV PYTHONPATH=/usr/local/lib/python2.7/site-packages
EXPOSE 5000
CMD ["app.py"]
构建阶段:
从 python:2.7-slim 的基础镜像末尾
将运用顺序复制到 /app 目录下
晋级 pip 并安装依赖
Distroless 阶段:
从 gcr.io/distroless/python2.7 的基础镜像末尾
将运用顺序从构建阶段的 /app 目录复制到以后阶段的 /app 目录
将 python 的 site-packages 从构建阶段复制到以后阶段的 site-packages 目录
设置任务目录到 /app,将 python PATH 设置为 site-packages 目录,并暴露 5000 端口
运用 CMD 指令运转 app.py
由于 Disroless 镜像不包含 shell,所以应该在最后运用 CMD 指令。假设不这样做,Docker 将以为它是一个 shell CMD,并试图这样执行它,但这是不任务的。
构建镜像:
$ docker build -t <your_docker_repo>/flask-hello-world-distroless .
Sending build context to Docker daemon 95.74kB
Step 1/12 : FROM python:2.7-slim AS build
---> eeb27ee6b893
Step 2/12 : ADD . /app
---> a01dc81df193
Step 3/12 : WORKDIR /app
---> Running in 48ccf6b990e4
Removing intermediate container 48ccf6b990e4
---> 2e5e335be678
Step 4/12 : RUN pip install --upgrade pip
---> Running in 583be3d0b8cc
Collecting pip
Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB)
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 20.0.2
Uninstalling pip-20.0.2:
Successfully uninstalled pip-20.0.2
Successfully installed pip-20.1.1
Removing intermediate container 583be3d0b8cc
...................................
Successfully installed Jinja2-2.11.2 MarkupSafe-0.23 click-7.1.2 flask-1.1.2 itsdangerous-0.24 werkzeug-1.0.1
Removing intermediate container c4d00b1abf4a
---> 01cbadcc531f
Step 6/12 : FROM gcr.io/distroless/python2.7
---> 796952c43cc4
Step 7/12 : COPY --from=build /app /app
---> 92657682cdcc
Step 8/12 : COPY --from=build /usr/local/lib/python2.7/site-packages /usr/local/lib/python2.7/site-packages
---> faafd06edeac
Step 9/12 : WORKDIR /app
---> Running in 0cf545aa0e62
Removing intermediate container 0cf545aa0e62
---> 4c4af4333209
Step 10/12 : ENV PYTHONPATH=/usr/local/lib/python2.7/site-packages
---> Running in 681ae3cd51cc
Removing intermediate container 681ae3cd51cc
---> 564f48eff90a
Step 11/12 : EXPOSE 5000
---> Running in 7ff5c073d568
Removing intermediate container 7ff5c073d568
---> ccc3d211d295
Step 12/12 : CMD ["app.py"]
---> Running in 2b2c2f111423
Removing intermediate container 2b2c2f111423
---> 76d13d2f61cd
Successfully built 76d13d2f61cd
Successfully tagged <your_docker_repo>/flask-hello-world-distroless:latest
登录到 DockerHub 并推送镜像:
docker login
docker push <your_docker_repo>/flask-hello-world-distroless:latest
登录到 DockerHub(或许你的私有镜像仓),你应该会看到容器镜像可以运用:
(责任编辑:admin)