启动容器时如何运行命令-Docker

时间:2018-12-20 18:38:55

标签: node.js docker npm

这是Dockerfile:

FROM nginx:stable-alpine

COPY ./mailservice /var/www/backend
COPY ./dist /usr/share/nginx/html
COPY ./docker/nginx_config/default.conf /etc/nginx/conf.d/default.conf
COPY ./docker/nginx_config/.htpasswd /etc/nginx

RUN chown -R nginx:nginx /usr/share/nginx/html/ \
    && chown -R nginx:nginx /etc/nginx/.htpasswd \
    && apk add --update nodejs nodejs-npm

WORKDIR /var/www/backend
RUN npm run start

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

但是我的RUN npm run start无法正常工作,我必须手动将shell附加到容器上,然后自行运行。容器启动后启动npm run start的正确方法是什么?

更新

CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT ["node", "server.js"]

这项工作可以吗?

4 个答案:

答案 0 :(得分:2)

最佳实践说,每个容器不应运行多个进程。除非您的应用程序是通过从唯一的 entrypoint 开始进行多次处理的方式制作的。

但是您可以使用一些解决方法。尝试检查以下问题:Docker multiple entrypoints

答案 1 :(得分:0)

已解决:

Dockerfile

FROM nginx:stable-alpine

COPY ./mailservice /var/www/backend
COPY ./dist /usr/share/nginx/html
COPY ./docker/nginx_config/default.conf /etc/nginx/conf.d/default.conf
COPY ./docker/nginx_config/.htpasswd /etc/nginx

RUN chown -R nginx:nginx /usr/share/nginx/html/ \
    && chown -R nginx:nginx /etc/nginx/.htpasswd \
    && apk add --update nodejs nodejs-npm

ADD ./docker/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod 755 /docker-entrypoint.sh

EXPOSE 80

WORKDIR /

CMD ["/docker-entrypoint.sh"]

docker-entrypoint.sh

#!/usr/bin/env sh

exec node /var/www/backend/server.js > /var/log/node-server.log &
exec /usr/sbin/nginx -g "daemon off;"

答案 2 :(得分:0)

您将构建时间(基本上是RUN指令)与运行时(ENTRYPOINT或CMD)混淆了,并且, 之后,您将违反规则:一个容器,一个进程,即使这不是神圣的。

我的建议是在此配置下使用Supervisord

[unix_http_server]
file=/tmp/supervisor.sock                       ; path to your socket file

[supervisord]
logfile=/var/log/supervisord/supervisord.log    ; supervisord log file
loglevel=error                                  ; info, debug, warn, trace
pidfile=/var/run/supervisord.pid                ; pidfile location
nodaemon=false                                  ; run supervisord as a daemon
minfds=1024                                     ; number of startup file descriptors
minprocs=200                                    ; number of process descriptors
user=root                                       ; default user
childlogdir=/var/log/supervisord/               ; where child log files will live

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock         ; use a unix:// URL  for a unix socket

[program:npm]
command=npm run --prefix /path/to/app start
stderr_logfile = /dev/stdout
stdout_logfile = /dev/stderr

[program:nginx]
command=nginx -g "daemon off;"
stderr_logfile = /dev/stdout
stdout_logfile = /dev/stderr

使用此配置,您会将日志重定向到标准输出,这是一个很好的选择 练习,而不是临时存储在容器中的文件,您也会 PID负责处理子进程,并使用特定规则重新启动它们。

您也可以尝试使用bash脚本来实现这一点,但可能会很棘手。

另一个最佳解决方案应该是使用带有网络名称空间的单独容器,以便 将NGINX请求转发到NPM上游...但是如果没有Kubernetes,就很难 维护,即使使用Docker也并非没有可能:)

答案 3 :(得分:0)

  • 您当前的方法在设计上根本是错误的。
  • 您当前的方法是使用容器的明确反模式
  • 请为您的应用创建一个Dockerfile
  • 请分别为nginx创建一个Dockerfile
  • 使用docker-compose来构建堆栈,也可以按照自己的方式进行构建
  • 始终在单独的容器上运行应用程序和代理