如何在Dockerfile中有效设置环境变量以安装指定版本的Node.js和Python?

Dockerfile中构建一个python+nodejs的镜像。关于环境变量一直掌握不好
我的Dockerfile:

# 使用指定版本的 Node.js 基础镜像
FROM python:3.12.7-slim

# 设置工作目录
WORKDIR /app

RUN apt update && apt install -y curl

RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash


# 设置环境变量以加载 NVM
ENV NODE_VERSION=20.17.0

# 安装项目依赖
COPY package*.json ./

RUN export NVM_DIR="$HOME/.nvm" && \
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \ 
    nvm -v && nvm install $NODE_VERSION && nvm use nvm install $NODE_VERSION && \
    node -v && \
    npm -v && \
    npm config set registry https://registry.npmmirror.com && \
    npm install -g node-gyp && \
    npm install

# 更新包列表并安装必要工具
RUN apt update && apt install -y make build-essential

# 清理缓存以减小 Docker 镜像大小
RUN apt clean && rm -rf /var/lib/apt/lists/*

# 复制项目文件到容器中
COPY . .


RUN export NVM_DIR="$HOME/.nvm" && \
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \
    npm run build


# 设置容器启动时的 ENTRYPOINT 脚本
ENTRYPOINT ["entrypoint.sh"]

EXPOSE 9003

# 启动项目
CMD ["npm", "run", "start:prod"]

因为 RUN 命令每一次都是新的层 环境变量无法共享给后面的RUN。就导致我每一条和nvm node相关的命令都需要先导入环境变量 这里还不是问题。最主要在CMD命令也出现了因为环境变量问题 导致npm命令找不到的问题。请教大神帮忙修改这个Dockerfile。
因为在apt无法很好的指定node版本 所以想通过nvm来安装指定版本的node

在网上查教程 说可以通过entrypoint.sh 文件来导入环境变量,但是当我导入后 之前正常的build 流程就会出错。所以我应该如何在docker中安装指定的node版本呢?

阅读 630
avatarAI BotBETA

在Docker中处理Node.js和Python的依赖时,直接使用官方提供的镜像并避免在构建过程中安装额外的包管理器(如NVM)通常是一个更好的选择。这样可以简化Dockerfile,并减少潜在的问题,如环境变量在层之间不共享的问题。

以下是一个修改后的Dockerfile示例,它直接从官方Node.js镜像和Python镜像中安装所需的版本,并避免了使用NVM:

# 使用multi-stage build来优化最终镜像大小
# 第一阶段:构建Python和Node.js依赖
FROM python:3.12.7-slim AS python-build
FROM node:16.17.0-slim AS node-build

# 设置工作目录
WORKDIR /app

# 复制Python项目文件
COPY requirements.txt /app/
RUN pip install -r requirements.txt

# 复制Node.js项目文件
COPY package*.json /app/
RUN npm install

# 第二阶段:合并Python和Node.js的依赖
FROM python:3.12.7-slim
COPY --from=python-build /app/ /app/
COPY --from=node-build /app/node_modules /app/node_modules

# 设置Node.js可执行文件路径
ENV PATH="/app/node_modules/.bin:$PATH"

# 复制剩余的项目文件
COPY . /app/

# 构建Node.js项目(如果需要)
RUN npm run build

# 设置容器启动时的脚本
COPY entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# 暴露端口
EXPOSE 9003

# 启动项目
CMD ["npm", "run", "start:prod"]

注意

  1. 多阶段构建:使用多阶段构建可以分别构建Python和Node.js的依赖,然后在最终的镜像中合并它们。这样可以确保每个阶段的构建都是最优化的,并且最终镜像只包含必要的文件和层。
  2. 环境变量:在这个示例中,没有直接使用NVM,因此不需要设置与NVM相关的环境变量。如果Node.js项目需要全局安装的npm包(如node-gyp),可以在node-build阶段中安装它们。
  3. npm包路径:通过设置PATH环境变量,可以确保Node.js的npm包在全局范围内可用。
  4. entrypoint.sh:你可以在这个脚本中设置任何启动前的环境变量或配置,确保它们在容器启动时生效。

这种方法的好处是减少了Dockerfile的复杂性,避免了在构建过程中安装额外的包管理器,并且通过多阶段构建优化了最终镜像的大小。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏