Docker 㧠node.js ãåããã¨ã㯠PID 1 ã«ãã¦ã¯ãããªã
ããã¯ãnode.js on Docker ã®æ§æ㧠2ã3æ¥ããã£ã¦ãã¾ã£ãæã®è©±ã§ããå¿ããªãããã«è¨é²ãã¦ããã¾ãããªããå°æ¥ã¯æ¹åã»æ¹è¯ããã¦ããããããã¾ããã®ã§ã注æãã ããã
ä½ãèµ·ãã£ãã®ã
node.js ã® Docker ã³ã³ãããã"docker stop" ã§ã³ã³ãããæ¢ãããã¨ãã¦ãæ£å¸¸ã«åæ¢ããã10ç§ãããçµéããå¾ã«å¼·å¶çµäºãã¦ãã¾ãã¨ããçç¶ãçºçãã¾ããããã¤ãçãããããªãã®ã§ãç¶æ ã¨ãã¿ã¤ãã³ã°ã¨ããããã£ãè¦å ã§ã¯ãªããããããæ ¹æ¬çã«ä½ããããããã¨èãããã¾ãã
1. node on Docker ã®æ§æ
Docker ã³ã³ããä¸ã§ node.js ãåãã¦ããã ãã®æ¥µãã¦ã·ã³ãã«ãªæ§æã§ãã®åé¡ãçºçãã¾ããã
node.js ã§åãã¢ããªã¯ã"Hello World" ãåºãã ãã®è¶ ç°¡å㪠hello.js ã§ãããããªæãã§ãã
const http = require('http'); http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(3000);
hello.js ã¢ããªã Docker ã«ä»è¾¼ãããã® Docker ãã¡ã¤ã«ã¯ä»¥ä¸ã®éãã§ãããã¼ã¹ã¨ãªã Docker ã¤ã¡ã¼ã¸ã¯ãDocker Hub 㧠node.js ãæä¾ãã node:8.4 (ç¾å¨ã®latest) ãå©ç¨ãã¾ããã
FROM node:latest ADD ./hello.js /usr/src/app/ EXPOSE 3000 CMD ["node", "/usr/src/app/hello.js"]
æ®éã«ãã«ããã¦ãçæããã¤ã¡ã¼ã¸ããã³ã³ãããä½ã£ã¦èµ·åãã¾ãããã¶ã … ç¡äºã«åä½ããã¯ãã§ãã
$ docker build -t nodetest . $ docker run --name hello_node -P 3000:3000 nodetest
2. åé¡ãçºçããã
åãã¦ãã node.js ã¢ããªã®ã³ã³ããã docker stop ã§åæ¢ãã¾ãã¨ãä»åã®åé¡ãçºçãã¾ãã
$ docker stop hello_node
æããã10ç§ã»ã©çµéããå¾ã«ã³ã³ãããåæ¢ãããã³ãããæ»ã£ã¦ããã¨æãã¾ããããã®åæ¢ã«10ç§ããããã¨ãåé¡ã§ãã
3. docker stop ã§ä½ãèµ·ãã£ã¦ãããï¼
“docker stop” ã³ãã³ããå®è¡ããã¨ãDocker ã¯ãã®ã³ã³ããã®ã«ã¼ãããã»ã¹ï¼ããªãã¡ãPID=1 ã®ããã»ã¹ï¼ã« SIGTERM ã·ã°ãã«ãæãã¾ãã
ãã®ã·ã°ãã«ãåä¿¡ããããã»ã¹ã¯ã該å½ããã·ã°ãã«ãã³ããªã³ã°å¦çãå®è¡ãã¾ããå¤ãã®ããã°ã©ã ã§ã¯ãSIGTEM ãåããå ´åãèªèº«ãå®å ¨ã«åæ¢ããã·ã°ãã«ãã³ããªã³ã°å¦çãå®è£ ããã¦ãã¾ãã
SIGTERM ãæããå¾ãDocker 㯠ã³ã³ããï¼ã«ã¼ãããã»ã¹ï¼ãçµäºããã¾ã§ ããã©ã«ã10ç§éå¾ ã¡ã¾ããããã¦ã10ç§çµéãã¦ãçµäºããªãå ´åã¯ãã³ã³ããã®ã«ã¼ãããã»ã¹ã«å¯¾ã㦠SIGKILL ãæãã¾ããSIGKILL ã¯å¼·å¶çµäºãæ示ãããã®ãªã®ã§ããããåä¿¡ããããã»ã¹ã¯ãç´ã¡ã«ABORTãã¾ãã
ãã®æãããã»ã¹ã®çµäºã«å¿ è¦ãªå¦çã¯å ¨ã¦ã¹ãããããã¾ãã®ã§ ABORT å¾ã¯æ£å¸¸ãªç¶æ ã§ãããã¨ãä¿è¨¼ããã¾ããããããã£ã¦ã次åèµ·åæã«ãã¾ãç«ã¡ä¸ãããªããªãçãæãã¬é害ã®ãªã¹ã¯ãããã¾ãã
ä»åã® node.js ã®ã³ã³ãããã10ç§å¾ã«åæ¢ãã¦ãã¾ããããã¯ããªãã¡ SIGKILL ã§å¼·å¶çµäºãã¦ãããã¨ã«ãªãããã®ã¾ã¾ã§ã¯ãã°ãæãã§ãã
åå 調æ»
A. ç©çãµã¼ãç°å¢ã¨ Docker ç°å¢ã§ã®éããæ¤è¨¼
ããã§ããããã Docker ã«èµ·å ããåé¡ãªã®ãï¼ ããã¨ã node.js ã®åé¡ãªã®ãï¼ãåãåãããã¨æãã¾ãã
ã¨ãããã¨ã§ãä»®æ³åããªãç©çãµã¼ãç°å¢ã¨ Docker ç°å¢ã®ä¸¡æ¹ã§ node.js ã® hello ã¢ããªãåããããã®ããã»ã¹ã«å¯¾ãã¦ãããã SIGTERM ãéä¿¡ãã¦ã¿ã¾ãã
(1ï¼ç©çãµã¼ãç°å¢ã§æ¤è¨¼
#### Terminal 1 㧠node ã¢ããªãèµ·å $ node hello.js #### Terminal 2 㧠node ã« SIGTERM ãéä¿¡ $ ps -ef | grep node ubuntu 8526 4061 3 05:21 pts/0 00:00:00 node hello.js $ kill -TERM 8526 #### æåãnode hello.js ã¯ãç´ã¡ã«åé¡ãªãçµäºãã
ãã¾ãããã¾ããã
ç©çãµã¼ãç°å¢ã«ããã¦ãSIGTERM ãåä¿¡ãã node.js ããã»ã¹ã¯ãç´ã¡ã«èªåèªèº«ãçµäºããã¦ãã¾ããããã«ãããnode.js 㯠SIGTERM ãåä¿¡ããéã®ã·ã°ãã«ãã³ããªã³ã°ããã¡ãã¨å®è£
ããã¦ãããã¨ãåããã¾ãã
(2) Docker ã³ã³ããç°å¢ã§æ¤è¨¼
#### nodeã¢ããªãå ¥ã£ã Docker ã³ã³ãããèµ·å $ docker run --name hello_node -d nodetest $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ef2b7ab09468 nodetest "node /usr/src/app..." 50 seconds ago Up 49 seconds 3000/tcp hello_node #### èµ·åããã³ã³ããã«ã¢ã¿ãã $ docker exec -it hello_node /bin/bash #### ---- hello_node ã³ã³ããå ---- # ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 1 01:53 pts/0 00:00:00 node /usr/src/app/hello.js root 16 0 0 01:54 pts/1 00:00:00 /bin/bash # kill 1 ### ããªãªãï¼ï¼
ãã¡ã§ãï¼ï¼
å¹¾ã SIGTERM ãæãã¦ãåå¿ãã¾ãããDocker ã³ã³ããã®å
ã® node ã¯ãä½ãã®çç±ã§ SIGTERM ãåä¿¡ã§ããªããããããã¯ã·ã°ãã«ãç¡è¦ãã¦ããããã«è¦ãã¾ãã
B. ããã»ã¹ID 1 ã«æ³¨ç®ãã¦ããã«èª¿æ»
Linux ã«ã¤ãã¦ãåç¥ã®æ¹ã¯ãDockerã³ã³ããå ã® node.js ããã»ã¹IDã “1” ã§ãããã¨ã«ãéããªãæªãããè¦ããããããã¾ããã
æ®éã® Linux ç°å¢ã«ããã¦ãããã»ã¹ID = 1 㯠init ããã»ã¹ã§ãããã㯠ã«ã¼ãã«ããèµ·åããã¾ãããï¼ç¹ã« Linux ã«ããã¦ã¯ï¼ããã»ã¹D=1 ã«å¯¾ãã¦ã·ã°ãã«ãéããã¨ã¯ããããå¶éããã¦ãã¾ãï¼see âman 2 kill" on Linuxï¼ã
ã¨ãããã¨ã§ãä»åº¦ã¯ãç¹ã«ãããã»ã¹ID 1 ã«ä½ãç¹æ®ãªçç±ãç¡ããï¼ã¨ãããã¨ãçæããªãããããã« node.js ã®ã½ã¼ã¹ã³ã¼ãã確èªããããåæ§ã®åé¡ããªãã£ããï¼ã¨ãã調æ»ãè¡ãã¾ããã
ã»
ã»ã»
ã»ã»ã»
è¦ã¤ãã¾ãã
ä¸è¨ãã¼ã¸ã®ãHandling Kernel Signalsãã¨ããã¨ããã«ãä¸è¨ã®è¨è¼ãããã¾ãã
Node.js was not designed to run as PID 1 which leads to unexpected behaviour when running inside of Docker. For example, a Node.js process running as PID 1 will not respond to SIGTERM (CTRL-C) and similar signals. As of Docker 1.13, you can use the –init flag to wrap your Node.js process with a lightweight init system that properly handles running as PID 1.
docker run -it –init node
You can also include Tini directly in your Dockerfile, ensuring your process is always started with an init wrapper.
ã¾ããããããããnode.js 㯠PID 1 ã§åãããã«è¨è¨ããã¦ããªãã¨ãããªã®ã§ Docker ã³ã³ããã§åããã¨ãã¯ãSIGTERM ã¨ã Ctrl+C ã¨ãå¹ããªãã¨ããã¾ãã«ãä»åã®åé¡ã«ã¤ãã¦è¨åããã¦ãã¾ãã
ããä¸ã¤ã"lightweight init system" ã¨ãããã¼ã«ããã£ã¦ãDocker ã§åããã¨ãã¯ãããã PID 1 ã¨ãã¦åä½ãããnode ã¯ãã®åããã»ã¹ ã«ããã°ãããããçãªãã¨ãæ¸ãã¦ããã¾ãã
ã¨ãããã"Tini" ã¨ãã便å©ãªãã®ããã£ãã®ãï¼ï¼ ããããDocker 1.13 ãã㯠“–init” ãªãã·ã§ã³ã§ãããèªåçã«ã©ããããããã«çµã¿è¾¼ã¾ãã¦ããã¨ãããã¨ã§ããç¥ããªãã£ãã
GitHub - krallin/tini: A tiny but valid `init` for containers
対å¦å 容
åé¡ã®åå ãåãã£ãã®ã§ãããç°¡åã«å¯¾çãã§ãã¾ããã¨ãããã¨ã§ãæ©é Docker æ¬ä½ã«ãçµã¿è¾¼ã¾ãã¦ãã “Tini” ãæ´»ç¨ãã¾ãã
çµå±ãä»åã¯ã以ä¸ã®ããã« Dockerfile ã« Tiny ã®è¨å®ã追å ããã ãã§ãä¸äº OK ã¨ãªãã¾ããã
FROM node:latest # Add Tini ENV TINI_VERSION v0.15.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini ENTRYPOINT ["/tini", "--"] # MyApp ADD ./test3.js /usr/src/app/ EXPOSE 3000 CMD ["node", "/usr/src/app/hello.js"]
ã¾ã¨ã
node 㯠PID1 ã§åä½ããããã«ãã¶ã¤ã³ããã¦ããªãã®ã§ã docker ã«ãããã¨ãã¯ãç´æ¥ Docker ã®ç®¡çããã»ã¹ï¼ã¤ã¾ãPID1ï¼ã«ããã®ã¯ããããï¼
Docker 㧠PID 1 㧠Linux ã® init ã¿ããã«å¶å¾¡ãã¦ããã Tiny ã¨ãã便å©ãªãã¼ã«ãããã®ã§ããããæ´»ç¨ããã¨ãããã
ãããããnode ããã®ä» ãµã¼ãããã°ã©ã ãDocker ãç´æ¥èµ·åããããã»ã¹ï¼ã¤ã¾ã PID 1 ã¨ãªãããã»ã¹ï¼ã¨ããã®ã¯ãããããåé¡ããããªãã¨æãã¾ãã
以åãUnicorn ã SIGTERM ã§ã¯ãªã SIGQUIT ãæå¾ ãã¦ãããDocker stop ã§ç°å¸¸çµäºãã¦ãã¾ãåé¡ã«ãééãã¦ãã¾ãã
ãªã®ã§ãåå¥ã«ä½æããã¹ã¼ããã¤ã¶ Shell ã§ã©ããããã¨ããä»åãç´¹ä»ãã Tiny ããã¾ããã¨ãããã®æ¹ãå®å ¨ã§ã¯ãªããï¼ã¨ãæè¿ã¯ããæã£ã¦ãã¾ãã
ãªããPID 1 ã¨ãã Tiny ã®ãã㪠lightweight init ããã°ã©ã ã¯ãä¾ãã°ãèªåèªèº«ã SIGTERM ãåä¿¡ããã¨ãã«ããã®ã·ã°ãã«ããåããã»ã¹ã¾ã§ãã¡ãã¨ä¼æãããããåããã»ã¹ãã¾ã³ãã«ãªããªããã wait ãããããããã£ã init ã®ä½æ³ã«åã£ããã®ã§ãªããã°ãªãã¾ããããã®è¾ºã¯ååã注æãã ããã
ãã¾ã
Docker ã§ä½¿ãã lightweight init ãã¡
ããã§ã¯ãDocker ã³ã³ãã㧠PID 1 ã®ããã»ã¹ã¨ãã¦ä½¿ãã Tiny ããç´¹ä»ãã¾ããããã®å¾èª¿ã¹ãã¨ããããã®ä»ã«ããå¹¾ã¤ãä¼¼ããããªãã®ãããã¾ããã®ã§ãã¾ã¨ãã¨ãã¦ã以ä¸ã«ãªã³ã¯ãã¦ããã¾ãã
Tiny
æ¬è¨äºã§ãç´¹ä»ãã lightweight init ãåéããéãDocker ã«ãçµã¿è¾¼ã¾ãã¦ãã “docker run” ã® “–init” ãªãã·ã§ã³ã§èªåçã«ã©ããã§ãã¾ãã
dumb-init
“Yelp” ã§ä½¿ç¨ãã¦ãã lightweight init
my_init
“baseimage-docker” ã¨ããæ¬æ¥ã® Linux ã«è¿ãããã»ã¹ç°å¢ã Docker ã§æä¾ãã¦ããããã®ã¤ã¡ã¼ã¸ã§ä½¿ç¨ãã¦ãã my_initããã¡ãã¯ãã«ãããã»ã¹ã管çã§ããããã§ãã
inits_on_docker/init_node.sh
ã¡ãªã¿ã«ãç§ã Shell ã§ç°¡æã«ä½æãã¦ã¿ã¾ãããnode.js å°ç¨ã§ããããã£ããã ãããç´¹ä»ããã¦ãã ãããï¼ã¤ã£ãã¿æè¿ï¼
inits_on_docker/init_node.sh at master · ngzm/inits_on_docker · GitHub
#!/bin/bash # # init_node.sh # - init process for aplications using node.js. # # Usage # - add your Dockerfile as follows. # ------------ # ADD ./init_node.sh /usr/local/bin # RUN chmod +x /usr/local/bin/init_node.sh # CMD ["init_node.sh", [path_to_your_app]] # ------------ # echo "start init_node.sh" # set application path path_to_your_app=${1:-''} if [ -z ${path_to_your_app} ]; then echo "require first argment for path_to_your_app" echo "quit this container" exit 1 fi if [ ! -e ${path_to_your_app} ]; then echo "${path_to_your_app} is not exists" echo "quit this container" exit 2 fi # Application PID initialize your_app_pid=0 # SIGINT handler int_handler() { echo "int_handler called" if [ ${your_app_pid} -ne 0 ]; then kill -INT ${your_app_pid} fi } # SIGTERM handler term_handler() { echo "term_handler called" if [ ${your_app_pid} -ne 0 ]; then kill -TERM ${your_app_pid} fi } # trap SIGINT - usually caught by Ctrl+c trap 'int_handler' INT # trap SIGTERM - sent when 'docker stop' trap 'term_handler' TERM # run application echo "run ${path_to_your_app}" node ${path_to_your_app} & your_app_pid="${!}" # wait untill the application (child process) will be killed wait ${your_app_pid} your_app_pid=0 echo "finish init_node.sh"
è£è¶³ã¨ã
ä½ããããªã«è¦å´ããªãã¦ãæåãã “npm run” ã§èµ·åããããã«ãã¦ããã°åé¡ãªãèµ·åã»çµäºãã§ãããã§ãï¼ã¨ããæ å ±ããã£ã¦ãä¸å¿åä½ããã¦ã¿ããããããã«è¦ãã¾ããã確ãã«ããã ã¨ãnode ã® PID 㯠1 ã§ã¯ãªããªãã®ã§ããæãã§ãã
ãã ããæ¬å½ã«ããã§ãåããã»ã¹ãå«ããã»ã¹ã¾ã§ç®¡çã§ãã¦ããã®ãï¼ããªãã¡ãã¾ã³ãã«ãªããã«ãã¾ãå¼·å¶çµäºããã«å¥å ¨ã«èµ·åãçµäºãã¦ããã®ãï¼ã¨ãã£ãã¨ããã¾ã§ã¯è£ä»ããã§ãã¦ãã¾ããããªã®ã§ç¶ç¶ãã¦èª¿ã¹ã¦ããããã¨æãã¾ãã
誰ãç¥ã£ã¦ãã人ãå± ãããã²æãã¦ãã ããã
æå¾ã«è¦æ ã§ã
docker-node/README ã®ãã¼ã¸ãæ¬å®¶ã®ããããã¼ã¸ã§æãã£ãã PID 1 ã§èµ·åããã¤ã³ã¹ãã©ã¯ã·ã§ã³ãã¦ãããã
docker-node/README.md at master · nodejs/docker-node · GitHub
ãã¨ããããªã·ãã¢ãªåé¡ããããªãããã£ã¨ç®ç«ã¤ã¨ããã§æ å ±å ¬éãã¦ãã ãã