[SadServers] 解説 "Salta": Docker container won't start.

2022/12/26に公開

"Salta": Docker container won't start.

SadServersの "Salta": Docker container won't start の解説です。

SadServers って何? って人は、 SadServers解説 を見てください。
一言でいうと、LeetCode (コーディング問題集) の Linuxサーバ設定版のようなものです。

問題

Scenario: "Salta": Docker container won't start.

Level: Medium

Description: There's a "dockerized" Node.js web application in the /home/admin/app directory. Create a Docker container so you get a web app on port :8888 and can curl to it. For the solution to be valid, there should be only one running Docker container.

/home/admin/app ディレクトリに "dockerized" Node.js web アプリケーションがあります。Docker コンテナを作成し、ポート :8888 でウェブアプリケーションを取得し、それに curl できるようにします。このソリューションを有効にするには、実行中のDockerコンテナが1つだけである必要があります。

Test: curl localhost:8888 returns Hello World! from a running container.

Time to Solve: 15 minutes.

OS: Debian 11

解説

まず、curlを実行してみます。 Dockerを動かしていないので、失敗(TCP接続ができない)することが期待です。

# `-v` により、詳細情報を出力

admin@ip-172-31-34-17:~/app$ curl -v http://localhost:8888
*   Trying 127.0.0.1:8888...
* Connected to localhost (127.0.0.1) port 8888 (#0)
> GET / HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Mon, 26 Dec 2022 09:56:54 GMT
< Content-Type: text/html
< Content-Length: 44
< Last-Modified: Fri, 16 Sep 2022 21:03:18 GMT
< Connection: keep-alive
< ETag: "6324e496-2c"
< Accept-Ranges: bytes
< 
these are not the droids you're looking for
* Connection #0 to host localhost left intact

どうも curl自体は成功しています。 Server: nginx/1.18.0と、あるので、nginxが動作しているようです。

systemctlnginxを止めます。

# nginx を止める。
admin@ip-172-31-34-17:~/app$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: en>
     Active: inactive (dead) since Mon 2022-12-26 09:57:18 UTC; 16s ago
       Docs: man:nginx(8)
    Process: 572 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process o>
    Process: 594 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=>
    Process: 1851 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 ->
   Main PID: 603 (code=exited, status=0/SUCCESS)
        CPU: 66ms

Dec 26 09:48:36 ip-172-31-34-17 systemd[1]: Starting A high performance web server>
Dec 26 09:48:36 ip-172-31-34-17 systemd[1]: Started A high performance web server >
Dec 26 09:57:18 ip-172-31-34-17 systemd[1]: Stopping A high performance web server>
Dec 26 09:57:18 ip-172-31-34-17 systemd[1]: nginx.service: Succeeded.
Dec 26 09:57:18 ip-172-31-34-17 systemd[1]: Stopped A high performance web server >

再度、curlを試します。

admin@ip-172-31-34-17:~/app$ curl -v http://localhost:8888
*   Trying 127.0.0.1:8888...
* connect to 127.0.0.1 port 8888 failed: Connection refused
* Failed to connect to localhost port 8888: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 8888: Connection refused

期待通り、失敗して、8888ポートが空きました。

さて、いよいよ Dockerを動かす準備をします。

# /home/admin/app/ に移動して、Dockerfileを確認。
admin@ip-172-31-35-220:/$ cd /home/admin/app/
admin@ip-172-31-35-220:~/app$ ls
Dockerfile  package-lock.json  package.json  server.js

Dockerfileをビルドして、実行します。
sudoをつけずにdockerコマンドを実行すると、Permissoin deniedエラーがでるので、sudoをつけます。

# nodeという名前でDockerイメージを作成する。
admin@ip-172-31-35-220:~/app$ sudo docker build -t node .
Sending build context to Docker daemon  101.9kB
Step 1/7 : FROM node:15.7-alpine
 ---> 706d12284dd5
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 463b1571f18e
Step 3/7 : COPY ./package*.json ./
 ---> Using cache
 ---> acfb467c80ba
Step 4/7 : RUN npm install
 ---> Using cache
 ---> 5cad5aa08c7a
Step 5/7 : COPY ./* ./
 ---> Using cache
 ---> a6ee5c4d5a96
Step 6/7 : EXPOSE 8880
 ---> Using cache
 ---> 0b18357df7c9
Step 7/7 : CMD [ "node", "serve.js" ]
 ---> Using cache
 ---> 1d782b86d6f2
Successfully built 1d782b86d6f2
Successfully tagged node:latest

# Dockerイメージ(node)を実行する。 
admin@ip-172-31-35-220:~/app$ sudo docker run -it --rm -p 8888:8888 node 
node:internal/modules/cjs/loader:928
  throw err;
  ^

Error: Cannot find module '/usr/src/app/serve.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:925:15)
    at Function.Module._load (node:internal/modules/cjs/loader:769:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Dockerイメージ(node)を実行するとエラーがでます。 Error: Cannot find module '/usr/src/app/serve.js'/usr/src/app/srve.js が無いといっています。

Dockerfileを確認します。

admin@ip-172-31-35-220:~/app$ cat Dockerfile 
# documentation https://nodejs.org/en/docs/guides/nodejs-docker-webapp/

# most recent node (security patches) and alpine (minimal, adds to security, possible libc issues)
FROM node:15.7-alpine 

# Create app directory & copy app files
WORKDIR /usr/src/app

# we copy first package.json only, so we take advantage of cached Docker layers
COPY ./package*.json ./

# RUN npm ci --only=production
RUN npm install

# Copy app source
COPY ./* ./

# port used by this app
EXPOSE 8880

# command to run
CMD [ "node", "serve.js" ]

ふむふむ、最終行の serve.js を実行しようとしています。
serve.jsがあるのか確認します。

admin@ip-172-31-35-220:/$ cd /home/admin/app/
admin@ip-172-31-35-220:~/app$ ls
Dockerfile  package-lock.json  package.json  server.js

存在するのは、server.jsなので、おそらく、Dockerfileのtypoですね。
また、port番号は8888なので、EXPOSE 8880も修正します。

admin@ip-172-31-35-220:~/app$ cat Dockerfile 
# documentation https://nodejs.org/en/docs/guides/nodejs-docker-webapp/

# most recent node (security patches) and alpine (minimal, adds to security, possible libc issues)
FROM node:15.7-alpine 

# Create app directory & copy app files
WORKDIR /usr/src/app

# we copy first package.json only, so we take advantage of cached Docker layers
COPY ./package*.json ./

# RUN npm ci --only=production
RUN npm install

# Copy app source
COPY ./* ./

# port used by this app
EXPOSE 8888   # <== 8888に修正

# command to run
CMD [ "node", "server.js" ]   # <== server.jsに修正

Dockerfileを修正したので、再度、docker buildをして、docker runをする。

admin@ip-172-31-35-220:~/app$ sudo docker build -t node .

admin@ip-172-31-35-220:~/app$ sudo docker run -it --rm -p 8888:8888 node 
Server Started on: 8888

正常に起動して、8888で待ち受けているようです。

curlで確認します。

admin@ip-172-31-34-17:~/app$ curl -v http://localhost:8888
*   Trying 127.0.0.1:8888...
* Connected to localhost (127.0.0.1) port 8888 (#0)
> GET / HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 12
< ETag: W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE"
< Date: Mon, 26 Dec 2022 09:59:51 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
* Connection #0 to host localhost left intact

Hello World!

Hello World!が返ってきました。成功です。

Discussion