最近在重构接入流水线,重构docker相关配置。
Dockerfile文件配置大概是这样(因为涉及私密,所以部分是使用伪代码)
# 基础构建镜像包含了私有化npm仓库鉴权登录 FROM node基础镜像 as builder WORKDIR /data/xxx-xxx # 先安装依赖,在依赖不变的情况下此层会使用cache COPY ./package*.json ./ #安装依赖 RUN npm i # 再copy其他代码文件到工作目录 COPY . . # 基础运行镜像,用这个镜像构建最终的运行镜像 FROM node运行镜像 # 拷贝构建后代码到工作目录 COPY --from=builder /data/xxx-xxx/ data/xxx-xxx # 设置需要挂载到宿主机的目录 VOLUME ["/data/xxx-xxx/logs"] # 暴露默认端口8890 EXPOSE 8080 # 从entrypoint.sh启动容器 ENTRYPOINT ["bash", "/data/xxx-xxx/entrypoint.sh"] # 下面的命令会在entrypoint.sh中调用 CMD ["npm", "run", "start:docker" ]
在entrypoint.sh中涉及到给目录文件授权操作,一般这是通用的需求。
#!/bin/bash set -e function env_check(){ local exit_ var_ exit_=false for var_ in "${@}";do if [[ -z "$(eval echo '$'"${var_}")" ]];then echo "${var_} is empty." exit_=true fi done if $exit_;then exit 1 fi } #环境变量检查 env_check USER_ID GROUP_ID RUN_USER="xxxxx" if [[ "$(id -u)" == "0" ]] && [[ "${USER_ID}" != "0" ]]; then # 修改/创建 xxxxx用户的uid和gid useradd -u ${USER_ID} ${RUN_USER} groupmod -g ${GROUP_ID} ${RUN_USER} # 目录授权 chown -R ${USER_ID}:${GROUP_ID} /data/xxx-xxx cd /data/xxx-xxx
# 命令授权 exec gosu ${USER_ID}:${GROUP_ID} $@ fi cd /data/xxx-xxx
# 执行外部的CMD命令 exec $@ set +e
但是当docker run -e USER_ID=1000 -e GROUP_ID=1000 docker_xxxx 时报错,说user_id 1000 is exist.
查询node docker镜像源码,发现原来node镜像做了授权操作,将uid和gid设置为了1000:1000
具体可以看:https://github.com/nodejs/docker-node/blob/master/10/stretch-slim/Dockerfile
解决办法有两个:
1.当USER_ID和GROUP_ID为1000时,就不进行授权操作,在entrypoint.sh脚本中通过if语句进行规避。
2.自己构建node镜像,将uid和gid修改为非1000的值(一般设置为低于1000)。
目前我们暂时是采用第一种做法。