Docker和Node.js最佳实践
Yanyan
・7 分钟阅读
.多客户环境和数据中心
以NODE_ENV
设置为production
运行,
-e "NODE_ENV=production"
全局npm依赖性
如果需要安装全局npm依赖项,建议将这些依赖项放在非root用户目录中。要实现这个,请将以下行添加到Dockerfile
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying path
升级/降级Yarn
本地
如果需要为本地安装升级降级,可以通过在Dockerfile
中发出以下命令来实现:
如果要全局升级yarn
,请按照下一节中的说明操作。
遵循本地安装指令时,由于重复的Yarn,镜像最终会变大。
FROM node:6
ENV YARN_VERSION 1.16.0
RUN yarn policies set-version $YARN_VERSION
全局
FROM node:6
ENV YARN_VERSION 1.16.0
RUN curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz"
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg
&& rm yarn-v$YARN_VERSION.tar.gz
如果使用的是基于alpine的镜像,则curl
将不存在,因此你需要确保在使用时已安装它:
FROM node:6-alpine
ENV YARN_VERSION 1.5.1
RUN apk add --no-cache --virtual .build-deps-yarn curl
&& curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz"
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn
&& ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg
&& rm yarn-v$YARN_VERSION.tar.gz
&& apk del .build-deps-yarn
处理内核信号
Node.js未设计为作为PID 1运行,在运行Docker的内部时会导致意外的行为,例如,作为PID 1运行的Node.js进程将不响应SIGINT
(CTRL-C
)和类似的信号,从Docker 1.13开始,你可以使用--init
标志来包装你的进程。
docker run -it --init node
您还可以将Tini直接包含在Dockerfile中,以确保始终使用init包装器启动您的过程。
非root用户
默认情况下,Docker以根用户身份运行容器,容器内部可能构成安全问题。你希望尽可能将容器作为非权限用户运行,node镜像为node
用户提供了这种用途,然后,Docker镜像可以通过以下方式与node
用户一起运行:
-u"node"
或者,可以在Dockerfile
中激活用户:
FROM node:6.10.3
...
# At the end, set the user to use when running this image
USER node
如果您不再需要在镜像中创建的用户,则可以使用以下命令将其删除:
# For debian based images use:
RUN userdel -r node
# For alpine based images use:
RUN deluser --remove-home node
如果需要更改用户的uid/gid,可以使用:
RUN groupmod -g 999 node && usermod -u 999 -g 999 node
如果你需要另一个用户名(ex,myapp
)执行:
RUN usermod -d /home/myapp -l myapp node
对于基于alpine的镜像,没有groupmod
和usermod
,因此要更改uid yf_xieyf gid,你必须删除以前的用户:
RUN deluser --remove-home node
&& addgroup -S node -g 999
&& adduser -S -G node -u 999 node
内存
如果在同一个主机上运行多个容器,就应该限制它们可以消耗多少内存。
-m "300M" --memory-swap "1G"
CMD
创建镜像时,可以绕过package.json
=s start
命令并将它直接发送到镜像本身,首先减少容器内部运行的进程数,其次,SIGTERM
和SIGINT
等退出信号由Node.js进程接收,而不是npm吞噬它们。
CMD ["node","index.js"]
运行Docker
以下是运行默认Node.js Docker容器化应用程序的示例:
$ docker run
-e "NODE_ENV=production"
-u "node"
-m "300M" --memory-swap "1G"
-w "/home/node/app"
--name "my-nodejs-app"
node [script]
安全
Docker团队提供了一个工具来分析运行中的容器是否存在潜在的安全问题,你可以从这里下载,并运行此工具:https://github.com/docker/docker-bench-security
node-gyp alpine
以下是在alpine variant上安装需要node gyp支持的软件包的依赖项的示例:
FROM node:alpine
RUN apk add --no-cache --virtual .gyp python make g++
&& npm install [ your npm dependencies here ]
&& apk del .gyp
下面是一个多级构建示例
FROM node:alpine as builder
## Install build toolchain, install node deps and compile native add-ons
RUN apk add --no-cache python make g++
RUN npm install [ your npm dependencies here ]
FROM node:alpine as app
## Copy built node modules and binaries without including the toolchain
COPY --from=builder node_modules .