Docker基础内容学习


前言

记录本周(25/6/30~7/6)在docker训练营(https://opencamp.cn/Docker/camp/202501)关于docker与cnb的学习到的知识与相关练习。


一、Docker基础

1.Docker简介

Docker 是一个开源的容器化平台。 它利用操作系统层级的虚拟化技术(主要是 Linux 的 cgroups 和 namespaces),将应用程序及其所有依赖项(代码、运行时环境、系统工具、系统库、配置文件等)打包成一个轻量级、可移植、自给自足的软件单元,称为 容器(Container)。这个容器可以在任何支持 Docker 的环境中(无论是开发者的笔记本电脑、物理服务器、虚拟机,还是云端)以完全相同的方式快速、可靠地运行。
以下是docker的几个关键概念:
容器(Container):容器是 Docker 的基本部署单元。它是一个轻量级的、独立的运行时环境,包含应用程序及其相关依赖。容器利用 Linux 内核的命名空间和控制组技术,实现了隔离性和资源管理,使得应用程序在不同的容器中运行不会相互影响。

镜像(Image):镜像是用于创建容器的模板。它包含了一个完整的文件系统,其中包括应用程序运行所需的所有文件、依赖和配置信息。镜像是不可变的,通过 Docker 镜像可以创建多个相同的容器实例。举例:操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系统的 root 文件系统。

镜像仓库(Image Registry):镜像仓库是用于存储和分发 Docker 镜像的地方。最常用的公共镜像仓库是 Docker Hub,上面有大量的官方和社区共享的镜像。此外,还可以搭建私有的镜像仓库,用于存放自己的镜像。

Dockerfile:Dockerfile 是一种文本文件,用于定义 Docker 镜像的构建过程。它包含了一系列的指令,用于指定基础镜像、安装软件、拷贝文件、配置环境等。通过 Dockerfile,可以自动化地构建镜像,确保镜像的一致性和可重复性。

2.Docker容器技术与虚拟技术的区别


在这里插入图片描述

从上图可以看出,传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,再在该系统上再运行所需应用进程。而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。所有容器共享 Host OS 内核,但通过 Linux cgroups 和 namespaces 实现进程隔离。

3.namespace – Docker容器隔离的基石

容器本身是一个被隔离的特殊进程。而Docker通过Namespace技术实现资源隔离,使得每个容器拥有独立的系统视图,仿佛运行在单独的Linux主机上。也就是说,每一个容器都有一套各自独立的namespace来隔离彼此。
在这里插入图片描述
Namespace是Linux内核的一项功能,用于 隔离系统资源,使得不同Namespace中的进程拥有独立的PID、Network、Mount等等。如PID Namespace用于隔离进程 ID,使容器内只能看到自己的进程。

4.Cgroup – Docker容器资源管控的核心

在这里插入图片描述
在 Docker 中,Cgroups(Control Groups) 的主要任务是 管理一个宿主机上所有容器的资源分配,但它的控制可以细化到 单个容器内的进程组。其功能主要包括以下几点:
资源限制:控制进程组使用的内存的上限,也包括文件系统和物理内存交换用的页缓存。
优先级分配:控制分配的CPU时间片数量、硬盘IO吞吐,也就是实际上控制了优先级。
资源统计:统计资源的使用量,比如CPU使用时长、内存用量等,从而计费。
进程控制:执行挂起、恢复进程组的操作。

5.个人使用到的部分Docker命令

(1) 镜像格式

<repository>/<image>:<tag> #镜像的一般格式

其中repository代表仓库,如果为空则默认为 Docker Hub;image代表镜像,分为 public 和 private 两种,对于 public 的镜像无需登录即可拉取,对于 private 的镜像则需要登录后才能拉取;tag标识镜像的版本,为空则默认为latest。举例:

docker.cnb.cool/looc/git-cnb:latest #/looc/git-cnb为image(镜像)

(2) 镜像相关

docker pull alipine #拉取镜像
docker images #查看镜像
dokcer search alipine #搜索镜像

#为镜像重新tag
docker tag <image_id> alpine-figlet

(3) 创建容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
# 举例:创建并允许 Nginx 容器
docker run -d --name dc1 -p 80:80 nginx #dc1为容器名,nginx为官方镜像名

#举例:查看容器的全部文件结构
docker run alpine ls -a #ls的功能是显示当前目录下的文件和文件夹,-a为all的意思

常用参数:
–name=NAME 为容器指定名字为NAME,不使用的话系统自动为容器命名
-d: 后台运行容器并返回容器ID,也即启动守护式容器(后台运行);

-i:以交互模式运行容器,通常与 -t 同时使用;
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
也即启动交互式容器(前台有伪终端,等待交互,一般连用,即-it);

-P: 随机端口映射,大写P
-p: 指定端口映射,小写p(主机端口:容器端口)

(4) 查看容器(ps)

docker ps #列出正在运行的容器
docker ps -a #显示 所有容器(包括已停止的)
docker ps -f #按条件过滤,如docker ps -f "status=running"
docker ps --format #自定义输出格式,如docker ps --format "{{.Names}}: {{.Status}}"

docker ps -a | grep nginx  # 查找包含"nginx"的容器
docker ps -a --filter "exited=1"  # 查看退出码为1的容器(通常出错)
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"
docker stop $(docker ps -q)  # 停止所有运行中的容器

(5) 其他容器相关命令

#启动并重新进入容器
docker start -ai<容器名>
-a:附加到容器的输出(类似-it的交互式效果)
-i:保持交互式输入

#启动容器后再附加
docker start<容器名>
docker attach<容器名>

#attach可能导致容器直接退出,因此建议使用docker exex:
docker exec -it<容器名> /bin/sh #新建一个shell会话

#手动删除已经停止的容器
docker rm <容器名>

#将现在容器提交为镜像
docker commit <容器ID> [新镜像名:标签]

二、DockerFile

1.基础概念

Dockerfile 是一个纯文本配置文件,包含了一系列构建 Docker 镜像的指令用于描述镜像的构建过程,包括基础映像、软件包安装、文件拷贝、环境变量设置等。它就像一份详细的"烹饪食谱",告诉 Docker 如何一步步创建出可运行的容器环境。
通过编写 dockerfile,可以将应用程序、环境和依赖项打包成一个独立的容器镜像,使其可以在不同的环境和平台上运行,实现应用程序的可移植性和可扩展性。
最终的构建流程是:1.编写dockerfile文件——>2.docker build 构建镜像——>3.docker run 镜像

2.相关指令

指令名称作用示例
FROM指定基础镜像,必须是 Dockerfile 的第一条指令。定义构建过程的起点。FROM ubuntu:22.04
RUN在构建过程中执行命令,用于安装软件包、创建目录等操作。每一条 RUN 指令会创建一个新的镜像层。RUN apt-get update && apt-get install -y nginx
COPY从构建上下文复制文件或目录到镜像中,保留文件属性和权限。比 ADD 更推荐使用,因 ADD 有额外功能可能造成混淆。COPY app.py /usr/src/app/
CMD指定容器启动时的默认执行命令(可被运行时覆盖)。一个 Dockerfile 只能有一个生效的 CMD。CMD ["python", "app.py"]
EXPOSE声明容器运行时监听的网络端口,仅作为文档说明(实际端口映射需在运行时通过 -p 参数指定)。EXPOSE 80
WORKDIR设置后续指令的工作目录,相当于 cd 命令。如果目录不存在会自动创建。WORKDIR /app
ENV设置环境变量,可在后续指令和容器运行时使用。支持键值对格式和空格分隔的多个变量。ENV APP_VERSION=1.0
ENTRYPOINT配置容器启动时的主执行程序(不可被运行时完全覆盖)。常与 CMD 配合使用,CMD 作为默认参数。ENTRYPOINT ["nginx"]
ARG定义构建时的变量(构建后不再存在),可通过 --build-arg 在构建时传入值。ARG USER=admin
VOLUME创建挂载点,用于持久化数据和共享文件。即使容器被删除,卷中的数据仍会保留。VOLUME /var/lib/mysql
USER指定后续指令的执行用户(以及运行容器时的默认用户),用于提升安全性。USER nobody
HEALTHCHECK定义容器健康检查命令,Docker 会定期执行以监控容器状态。`HEALTHCHECK --interval=30s CMD curl -f http://localhost/

三、已完成相关练习

1.基础exercise1

题目要求

练习 1:基础镜像和命令使用

要求:
1. 使用 ubuntu:22.04 作为基础镜像
2. 安装 nginx 和 curl 包
3. 创建一个简单的 HTML 文件,内容为 "Hello Docker!"
4. 将 HTML 文件复制到 nginx 的默认网站目录
5. 暴露 80 端口
6. 启动 nginx 服务

提示:
- 使用 apt-get update 和 apt-get install 安装软件包
- nginx 的默认网站目录是 /var/www/html/
- 使用 CMD 或 ENTRYPOINT 启动 nginx
完成这个 Dockerfile 后,构建镜像并运行容器,访问 http://localhost:8080 应该能看到 "Hello Docker!" 页面

dockerfile代码:

FROM ubuntu:22.04
#更新并安装nginx与curl包
RUN apt-get update && \
    apt-get install -y nginx curl 
#创建一个html文件并复制到nginx的网站目录
RUN echo "Hello Docker!" > /var/www/html/index.html
#暴露端口80
EXPOSE 80
#启动nginx,"-g"代表Nginx的全局配置参数标志,"daemon off;"让Nginx以前台模式运行(防止容器退出)
CMD ["nginx", "-g", "daemon off;"]

2.基础exercise2

题目要求:

练习 2:Python 应用构建

要求:
1. 创建一个简单的 Python Flask 应用的 Dockerfile
2. 实现以下功能:
   - 使用 python:3.11-slim 作为基础镜像
   - 安装应用依赖
   - 创建非 root 用户运行应用
   - 配置工作目录
   - 设置环境变量
   - 暴露应用端口

提示:
- 使用 requirements.txt 管理依赖
- 使用 WORKDIR 设置工作目录
- 使用 USER 指令切换用户
- 使用 ENV 设置环境变量

测试命令:
docker build -t exercise2 .
docker run -d -p 5000:5000 exercise2
curl http://127.0.0.1:5000 | grep -q "Hello Docker"

dockerfile代码:

FROM python:3.11-slim

# 设置容器内环境变量
ENV FLASK_APP=app.py \
    FLASK_RUN_HOST=0.0.0.0 \
    PORT=5000

# 创建工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install  -r requirements.txt && \
    # 创建用户组和用户
    addgroup  appuser && \
    adduser  --ingroup appuser appuser

# 复制应用代码
COPY . .

# 修改文件所有权给非 root 用户
RUN chown -R appuser:appuser /app

# 切换到非 root 用户
USER appuser

# 暴露应用端口
EXPOSE $PORT

# 设置容器启动命令
CMD ["flask", "run"]

3.基础exercise3

题目要求:

练习 3:Rust 多阶段构建

要求:
1. 使用多阶段构建来优化 Rust 应用的 Docker 镜像
2. 第一阶段:
   - 使用 rust:1.75-slim 作为基础镜像
   - 设置工作目录
   - 复制 Cargo.toml 和 Cargo.lock(如果存在)
   - 复制源代码
   - 安装 MUSL 目标环境, 支持交叉编译 rustup target add x86_64-unknown-linux-musl
   - 使用 cargo build --target x86_64-unknown-linux-musl --release 构建应用
3. 第二阶段:
   - 使用 alpine:latest 作为基础镜像
   - 从第一阶段复制编译好的二进制文件
   - 设置工作目录
   - 运行应用

提示:
1. 使用 COPY --from=builder 从构建阶段复制文件
2. 注意文件权限和所有权
3. 确保最终镜像尽可能小, 小于 20 M

测试命令:
docker build -t rust-exercise3 .
docker run rust-exercise3

dockerfile代码:

# 第一阶段:构建阶段
FROM rust:1.75-slim AS builder

# 设置工作目录
WORKDIR /app

# 先复制依赖声明文件;使用通配符*时,如果匹配不到不会报错只是跳过
COPY Cargo.toml Cargo.lock* ./

# 复制源代码
COPY src ./src

# 安装 MUSL 编译目标(静态链接库,Alpine 必需)
RUN rustup target add x86_64-unknown-linux-musl

# 编译应用(使用 MUSL 目标,静态链接依赖)
RUN cargo build --target x86_64-unknown-linux-musl --release

# 第二阶段:运行阶段(使用最小化 Alpine 镜像)
FROM alpine:latest

# 安装 CA 证书(某些 HTTPS 请求可能需要)
RUN apk --no-cache add ca-certificates

# 设置工作目录(二进制文件将放在这里)
WORKDIR /app

# 精确复制
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/rust-docker-example ./

# 设置容器启动命令(运行二进制文件)
CMD ["./rust-docker-example"]

总结

在本周完成了docker中基础内容的学习与练习,争取加快学习后续相关知识并完成至少一个项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值