在学习docker 我更希望你因该是学会如何用!
window是有电脑端,可视化操作加上一点命令足够。
首先你要明白docker 这一套,docker 和docker compose是什么? 学习路劲就是:
- 学习写一个docekrfile,
- 学习使用docker compose 去传参你的镜像
docekr 就是虚拟一台电脑去放你开发应用程序,因此这台电脑的环境变量全是关于你项目的。 就会运行的非常快,虽然体积有些大。好处还有可以把这个镜像到处运行。
编写一个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"]
这个Dockerfile其实要注意的是:构建时和运行时。 请你记住构建时是Dockerfile 因为正在打包嘛。docker compose 是运行时。 这个Dockerfile里面的变量有arg 和env 两种,arg 用于构建时就确定的变量,env 用于docker compose 后面可以传参的变量。
docker Compose 文件详解
是因为docker 启动一般会给很多参数,比如 -e 、 -env_file指定环境变量 -v 指定还在卷 网络配置等,导致一大串,所以出现compose 组合,把这些变量统统放到一个文件,我要启动,给别人发这个,按个插件就是能启动。
示例
services: #固定写法 服务
nest-admin-server: # 服务名称
build: . # 这个地方要么images :指定镜像,他回去下载,在运行,写build 就会,在当前文件寻找dockerfile 进行构建。 "." 是当前目录
#两者二选一
#build:
#context: .
#dockerfile: Dockerfile.prod # 明确指定文件名
container_name: nest-admin-server #容器名称
pull_policy: always # 不管本地有没有这个镜像都去下载
restart: always #是否重启
command: [ "pm2-runtime", "ecosystem.config.js" ] # 指定一些命令,容器开机运行的名称,可以与dockerfile 最后的entry 结合使用
env_file: #指定环境变量,记住,文件的env变量只能用于这个compose 文件,因为是运行时,所以构建时,dockerfile 不要这里面的变量。
- .env
- .env.production
ports:
- '${APP_PORT}:${APP_PORT}' # 这些变量是来自envfile
volumes: # 持久化,就是把产生的数据,保存到你期望的地方
- db_data:/var/lib/postgresql/data
networks:
- nest_admin_net #这个地方指定使用那种网络,网桥可以访问外网,和主机通信,基本等于
networks: #创建一个网络,你可以当成路由器
nest_admin_net:
name: nest_admin_net
dirver: bridge #网桥,要是不懂去看技术蛋老师的网络协议
volumes:
db_data:
Z
补充一个很有用东西--调试
docker compose 检查
#查看docker compose配置如何
#查看默认指定env_file 的配置
docker compose config
# 查看实际生效的环境变量值
docker compose --env-file .env.prod config
docker file 的调试
1.使用 RUN
命令打印变量
ARG PROJECT_DIR=/appENV
PROJECT_DIR=$PROJECT_DIR
# 打印变量值
RUN echo "PROJECT_DIR is set to: $PROJECT_DIR" && \
echo "Current working directory: $(pwd)"
环境
开发环境
docker compose -f docker-compose.yml
生产环境
docker compose -f docker-compose.prod.yml up
注意事项
dockercompose 去默认读取同级目录下的 .env
关于环境变量优先级:
正确优先级:
docker run -e
> compose environment
> env_file
> Dockerfile ENV
.env 只有 docker compose
会默认读取,docker build
需要显式指定
bridge
是默认网络驱动,不需要显式声明。
更准确的描述应该是:"默认创建的 bridge 网络允许容器间通信,并通过 NAT 访问外网"