全栈工程师:运维篇(一)docker 详解

334 阅读5分钟

# 简说

docker 非常需要实践,我是先看了两三集视频,先耍会了桌面版,再来仔细研读docker。

两座大山:

  1. 构建时和运行时
  2. 变量优先级
  3. 做实验🧪了解变量传递(这个算提醒)

# docker 命令表

# 一、容器操作(核心)
# 创建并启动容器(后台运行)
docker run -d --name nginx_test -p 8080:80 nginx:latest
# 注释: -d 代表后台运行;--name 指定容器名称;-p 指定端口映射(宿主机端口:容器端口);nginx:latest 代表容器镜像名

# 查看运行中的容器
docker ps
# 注释: 仅查看当前正在运行的容器

# 查看所有状态的容器(运行中+已停止)
docker ps -a
# 注释: -a 表示查看全部,包含已停止的容器

# 删除容器(强制删除,无论是否运行)
docker rm -f nginx_test
# 注释: -f 强制删除;nginx_test 是容器名称

# 删除容器(通过容器ID删除,强制删除)
docker rm -f 95c4e06a3284
# 注释: 95c4e06a3284 是容器ID(可通过docker ps -a查看)

# 启动已停止的容器
docker start nginx_test
# 注释: nginx_test 是容器名称(或用容器ID)

# 停止运行中的容器
docker stop nginx_test
# 注释: nginx_test 是容器名称(或用容器ID)

# 重启容器(无论当前是否运行)
docker restart nginx_test
# 注释: nginx_test 是容器名称(或用容器ID)

# 查看容器日志(实时查看)
docker logs -f nginx_test
# 注释: -f 实时跟踪日志;nginx_test 是容器名称(或用容器ID)

# 进入容器内部(交互模式)
docker exec -it nginx_test /bin/bash
# 注释: -it 开启交互模式;nginx_test 是容器名称;/bin/bash 进入容器的命令行

# 查看容器详细信息
docker inspect nginx_test
# 注释: 查看容器的IP、配置、挂载等所有详细信息

# 二、镜像操作
# 查看服务器上已存在的所有镜像
docker images
# 注释: 显示镜像名称、标签、ID、创建时间、大小

# 删除服务器上已存在的镜像
docker rmi redis:latest
# 注释: redis:latest 是镜像名+标签;若镜像被容器引用,需先删除容器再删除镜像

# 强制删除镜像(忽略容器引用)
docker rmi -f redis:latest
# 注释: -f 强制删除,即使镜像被容器引用

# 拉取镜像(从Docker Hub下载)
docker pull nginx:latest
# 注释: nginx:latest 是镜像名+标签;latest 表示最新版本,可指定具体版本(如nginx:1.24)

# 推送镜像到仓库(需先登录仓库)
docker push 镜像名:标签
# 注释: 推送前需用 docker login 登录对应仓库(如Docker Hub、私有仓库)

# 搜索镜像(从Docker Hub搜索)
docker search nginx
# 注释: 搜索包含nginx关键词的镜像,显示镜像名、描述、星级等

# 三、Docker服务操作
# 启动Docker服务
systemctl start docker
# 注释: 适用于Linux系统;Windows系统可通过服务管理器启动Docker Desktop Service

# 停止Docker服务
systemctl stop docker
# 注释: 适用于Linux系统;Windows系统可通过服务管理器停止Docker Desktop Service

# 重启Docker服务
systemctl restart docker
# 注释: 适用于Linux系统;Windows系统可通过服务管理器重启Docker Desktop Service

# 查看Docker服务状态
systemctl status docker
# 注释: 适用于Linux系统,查看Docker服务运行状态

# 设置Docker服务开机自启
systemctl enable docker
# 注释: 适用于Linux系统,设置Docker服务开机自动启动

# 四、数据卷操作(持久化)
# 创建数据卷
docker volume create my_volume
# 注释: my_volume 是数据卷名称,用于容器数据持久化,避免容器删除后数据丢失

# 查看所有数据卷
docker volume ls
# 注释: 查看服务器上所有已创建的数据卷

# 删除数据卷
docker volume rm my_volume
# 注释: my_volume 是要删除的数据卷名称

# 查看数据卷详细信息
docker volume inspect my_volume
# 注释: 查看指定数据卷的挂载路径、配置等详细信息

# 启动容器时挂载数据卷
docker run -d --name nginx_test -v my_volume:/usr/share/nginx/html nginx:latest
# 注释: -v 挂载数据卷;my_volume 是数据卷名称;/usr/share/nginx/html 是容器内挂载路径

# 五、其他常用命令
# 查看Docker版本信息
docker version
# 注释: 查看Docker客户端和服务端的版本信息

# 查看Docker系统信息(包含容器、镜像、数据卷等)
docker info
# 注释: 查看Docker系统的详细信息,包括容器数、镜像数、数据卷等

# 清理Docker无用资源(容器、镜像、数据卷等)
docker system prune
# 会删除已停止的容器、未被使用的镜像和数据卷,释放磁盘空间;添加 -a 可删除所有未被使用的资源

# 登录Docker仓库(如Docker Hub)
docker login
# 注释: 输入用户名和密码即可登录,登录后可拉取私有镜像、推送镜像

# 退出Docker仓库登录
docker logout
# 注释: 退出当前登录的Docker仓库账号

## 注意

  1. Dockerfile 的调试 使用 RUN 命令打印变量
ARG PROJECT_DIR=/app
ENV PROJECT_DIR=$PROJECT_DIR
# 打印变量值
RUN echo "PROJECT_DIR is set to: $PROJECT_DIR" && \
    echo "Current working directory: $(pwd)"

## 关于环境变量

Docker 环境变量的优先级遵循一个核心原则:来源越靠后,优先级越高,会覆盖之前同名的变量

对于 docker run -e 和 Dockerfile 中定义的环境变量,它们的优先级顺序从低到高如下:

  1. ENV Dockerfile 中的 - 这是在构建镜像时设置的默认值。它为应用程序提供了一个基础配置,但也是最容易被覆盖的一层。
  2. docker run --env-file - 当你使用 --env-file 选项从文件中加载环境变量时,文件里的变量会覆盖 Dockerfile 中同名的 ENV 设定。
  3. docker run -e--env - 这是最高优先级。在 docker run 命令中通过 -e 显式指定的环境变量,会覆盖所有其他来源(包括 Dockerfile 和 env-file)中的同名变量。

📜 优先级总结

简单来说,最终生效的值由以下顺序决定(后定义的覆盖先定义的): ENV--env-filedocker run -e Dockerfile < <

💡 举个例子

假设你有以下配置:

  • Dockerfile:
# dockerfile
ENV NAME=default
ENV VERSION=1.0
  • app.env 环境文件 :
VERSION=2.0

构建镜像后,运行容器的命令如下:

docker build -t myapp .
docker run -e NAME=production --env-file app.env myapp env

在这个例子中:

  • NAME 的最终值是**production**,因为 docker run -e 的优先级最高。
  • VERSION 的最终值是 2.0,因为它在app.env 文件中定义,优先级高于 Dockerfile 中的默认值 1.0

## 编写一个Dockerfile

# 使用多阶段构建减少最终镜像体积
# alpine 是镜像很小的版本  AS base 标识一个阶段
FROM node:22-alpine AS base
# 参数和变量定义
## ARG 一般用于在构建时就确定的变量。 比如软件名称、版本、项目目录等等
## ENV 一般用于你compose 或者你后期启动期望随时改变的变量,比如运行端口,容器挂载相关
ARG PROJECT_DIR="/app"   #给默认值
ENV PNPM_HOME="/pnpm" \  #多个变量使用""反斜杠 分割
  PATH="$PNPM_HOME:$PATH" # 注入pnpm到环境变量  后面$PATH 系统环境自带
# 安装全局依赖
# corepack 好像自带pnpm ,不需要安装pnpm
# pm2 是一个运行nodejs应用的xxx
RUN corepack enable && corepack prepare pnpm@latest --activate
RUN npm i -g pm2

# 设置工作目录
# WORKDIR 指定当前位置  不用cd,mkdir这些去指定代码放在哪里了
WORKDIR $PROJECT_DIR 

# nest 打包构建有些多,直接全带走
# copy  source  target 
# 指定了 workdir,WORKDIR ===  "./" 当前位置,所以下面两个相等
# COPY .  ./  相等
COPY ./  $PROJECT_DIR

#  设置时区
RUN apk add --no-cache tzdata && \ 
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

# 生产依赖 安装 --prod 指定 子安装生产依赖
FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile 

## 构建全部安装
# FROM base 从base阶段的结束开始续下面,
FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

# 构建
RUN pnpm run build

# --- 生产阶段 ---  转移构建产物
COPY --from=prod-deps $PROJECT_DIR/node_modules $PROJECT_DIR/node_modules
COPY --from=build $PROJECT_DIR/dist $PROJECT_DIR/dist

# 暴露端口 这个端口一般只声明
EXPOSE ${APP_PORT}

# 启动命令
# entrypoint  和cmd 可以对比,区别是,entry 可以接受参数,更加后面
CMD ["pm2-runtime", "dist/main.js"]

## 总结:

  1. 环境变量优先级 ENV--env-filedocker run -e Dockerfile < <
  2. Dockerfile其实要注意的是:构建时和运行时,请你记住构建时是Dockerfile 因为正在打包嘛。docker compose 是运行时。
  3. Dockerfile里面的变量有 ARG 和 ENV 两种,ARG 用于构建时就确定的变量,ENV 用于运行时可以传参改变原先的变量。