logo
0
0
Login
Forkfromcoldenn/docker-open-camp/knowledge-base, ahead:main2 commits

知识库实训课程

仓库目录结构

. ├── .cnb │ └── settings.yml # 知识库角色配置 ├── .cnb.yml # CNB 配置文件 ├── README.md ├── assets # 图片资源 └── knowledge # 知识库参考文件目录 └── huangmenji.md └── xxx

问题示例

  • 黄焖鸡怎么做?
  • Dockerfile 为什么如此重要呢?

如何创建知识库

1. Fork 本仓库

fork 本仓库到自己的组织下 fork

2. 添加参考文件

knowledge目录下添加任意 markdown 格式参考文件 add-md 仓库中.cnb.yml文件中已经内置知识库插件:

main: push: - stages: - name: build knowledge base image: cnbcool/knowledge-base settings: include: "knowledge/**.md"

提交的 markdown 文件会被自动处理,并生成知识库

3. 观察知识库处理结果

点击仓库云原生构建页面,查看构建过程及结果 cloud

查看最终结果 knowledge-base

4. 点击知识库按钮进行问答

knowledge-base-button

提问后,观察是否成功引用知识库中的文件 answer

如何完成大作业

本仓库的README文件已经内置好问题,即Dockerfile 为什么如此重要呢? 需要参考据配置知识库的过程,将 Docker训练营课程仓库(链接)的与此文件关联的README.md文件添加到知识库参考文件中,使得仓库的“知识库”回答这个问题时能够正确引用所添加的参考文件。

复制md文档时,请确保文件和Docker训练营课程仓库文件内容完全一致,fork的仓库记得同步上游

如何提交大作业

向本仓库提交 Pull Request(合并请求),命名格式为:姓名-大作业,例如:张三-大作业

提交完之后,本仓库流水线会自动向你Fork的仓库知识库发送请求,并且检测能否引用参考文献来回答Dockerfile 为什么如此重要呢?这个问题。

点击本仓库的云原生构建页面,查看构建过程及结果。

提交前如何自测

搜集相关md文件放入knowledge目录下,来到仓库的web页面,直接点击README文件的此问题,观察知识库是否正确引用参考文件进行回答 self-test

自定义镜像之 Dockerfile 详解

上节课我们学习了Docker概述,并实操理解了 Docker 三个核心概念:镜像、容器、仓库。 并且我们已经会使用 Docker 官方提供的镜像,启动容器。

但是这些镜像不能满足我们的需求,比如想定制一个个性化的环境,安装一些特定的软件,这个时候就需要我们自定义镜像。

本节课我们会学习两种自定义镜像的方式,一种是命令式创建镜像,一种是声明式创建镜像。 我们先从最简单的镜像创建方式开始,命令式创建镜像。

命令式创建镜像(从容器创建镜像)

案例:创建一个自定义镜像,基于alpine镜像,并安装figlet工具。 (figlet:输出艺术字符串的小工具)

docker run -it --name alpine alpine

然后我们进入容器,在容器中执行一些命令(安装一个软件),然后退出容器。

docker exec -it alpine /bin/sh apk update apk add figlet exit

这样,我们就在 alpine 容器中安装了 figlet 工具。

然后我们需要将这个新的容器环境跟其他人分享,我们可以通过 commit 命令将容器保存为一个镜像。

docker ps -a #查看容器 docker commit ${container_id} alpine-figlet

这样,我们就创建了一个名为alpine-figlet的镜像

最后我们就可以使用这个新的镜像了, 运行体验下艺术字生成的效果。

docker run alpine-figlet figlet "hello docker"

最后我们也可以使用 docker push 命令将镜像推送到镜像仓库中,其他人便可以使用 docker pull 来使用这个镜像了。

上述从容器创建镜像的方式虽然简单易懂,但是考虑真实项目中,我们可能需要安装很多工具,比如 git,vim,curl,wget 等等。如果我们每次都使用这种方式来创建镜像,就会非常麻烦,并且容易出错。

命令式创建的局限性

  1. 不可重复性:容器安装过程依赖人工操作,无法保证环境一致性
  2. 臃肿镜像:容器可能包含临时文件/缓存,导致镜像体积膨胀
  3. 安全风险:无法追溯安装过程,可能存在安全隐患
  4. 维护困难:无法版本化管理构建步骤

因此,我们需要一种更加方便的镜像创建方式,这就是 Dockerfile。

声明式创建镜像(Dockerfile)

我们来使用 Dockerfile 来自定义一个同样的镜像。它的格式是:

docker build -t alpine-figlet-from-dockerfile . docker run alpine-figlet-from-dockerfile figlet "hello docker"

这样当我们需要安装 git 的时候,只需要修改 Dockerfile 中的命令后重新构建镜像即可。

docker build -t alpine-figlet-from-dockerfile . docker run alpine-figlet-from-dockerfile git

小结

关于Dockerfile,上节课我们介绍部署技术历史中提及过,它的出现,帮助 Docker 成为容器化时代下最受欢迎的方案

那它到底是什么呢?

Dockerfile是一种静态文件,用来声明镜像的内容。

它为什么如此重要呢?

Dockerfile给容器化实践提供了一种规范,让创建镜像的操作简单化,标准化。 简单化让开发者可以快速上手,标准化让镜像可以重复使用,可移植,可复用。这些好处从侧面上推动了 Docker 的普及。

Dockerfile实践&关键语法介绍

为了上手书写 Dockerfile,我们还要学习它的语法。我们用两个🌰。

使用 Dockerfile 构建一个 jupyter notebook 镜像

让我们使用 Docker 来构建一个真实可用的镜像,比如 jupyter notebook 镜像。Dockerfile

docker build -t jupyter-sample jupyter_sample/

该镜像使用 RUN 指令来安装 jupyter notebook,使用 WORKDIR 指令设置工作目录, 使用 COPY 指令将代码复制到镜像中,使用 EXPOSE 指令来暴露端口, 最后使用 CMD 指令来启动 jupyter notebook 服务。

使用上述镜像来启动 jupyter notebook 服务。

docker run -d -p 8888:8888 jupyter-sample

我们使用了 -p 参数来将容器内的 8888 端口映射到宿主机的 8888 端口,在 cnb 上我们可以通过添加一个端口映射来实现外网访问。

port_forward

点击这个浏览器图标,就可以访问 jupyter notebook 服务了。

使用多阶段构建来打包一个 golang 应用

在实际开发中,我们经常需要构建 golang 应用。 如果使用传统的单阶段构建,最终的镜像会包含整个 Go 开发环境,导致镜像体积非常大。 通过多阶段构建,我们可以创建一个非常小的生产镜像。

创建一个 main.go 文件, 一个普通构建的 Dockerfile 以及一个多阶段构建的 Dockerfile

构建镜像:

docker build -t golang-demo-single -f golang_sample/Dockerfile.single golang_sample/ docker build -t golang-demo-multi -f golang_sample/Dockerfile.multi golang_sample/

运行容器:

docker run -d -p 8080:8080 golang-demo-single docker run -d -p 8081:8081 golang-demo-multi

容器运行成功后可以通过如下命令行来访问,可以看到两个容器都是在运行我们写的 golang 服务。

curl http://localhost:8080 curl http://localhost:8081

让我们来对比一下单阶段构建和多阶段构建的区别:

# 查看镜像大小 docker images | grep golang-demo

你会发现最终的镜像只有几十 MB,而如果使用单阶段构建(直接使用 golang 镜像),镜像大小会超过 1GB。这就是多阶段构建的优势:

  • 最终镜像只包含运行时必需的文件
  • 不包含源代码和构建工具,提高了安全性
  • 大大减小了镜像体积,节省存储空间和网络带宽

这种构建方式特别适合 Go 应用,因为 Go 可以编译成单一的静态二进制文件。在实际开发中,我们可以使用这种方式来构建和部署高效的容器化 Go 应用。

Dockerfile 命令

Dockerfile_commands

构建过程

  • 每个保留关键字(指令)都必须是大写字母
  • 从上到下顺序执行
  • "#" 表示注释
  • 每一个指令都会创建提交一个新的镜像层并提交

CMD 和 ENTRYPOINT 的区别

  • CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效可被替代
  • ENTRYPOINT # 指定这个容器启动的时候要运行的命令, 可以追加命令

Dockerfile 优化技巧

  • 层合并:合并 RUN 指令减少镜像层数
    RUN apk update && \ apk add --no-cache figlet git && \ rm -rf /var/cache/apk/*
  • 多阶段构建:构建多个镜像层,最后只保留最终的镜像层
  • 使用 .dockerignore 文件来忽略不需要的文件
  • 避免硬编码敏感信息,而是使用环境变量
    ARG DB_PASSWORD ENV DB_PASSWORD=${DB_PASSWORD}
  • 使用特定版本的基础镜像,避免因基础镜像更新导致的不稳定性
    FROM alpine:3.14 # 明确指定版本

About

No description, topics, or website provided.
2.09 MiB
9.08 KiB
0 forks0 stars2 branches0 TagREADME