docker docker-compose 详解

15 阅读3分钟

在学习docker 我更希望你因该是学会如何用!

window是有电脑端,可视化操作加上一点命令足够。

首先你要明白docker 这一套,docker 和docker compose是什么? 学习路劲就是:

  1. 学习写一个docekrfile,
  2. 学习使用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 访问外网"