Scenario: “Salta”: Docker container won’t start.
Level: Medium
Type: Fix
Tags: docker realistic-interviews
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.
Test: curl localhost:8888
returns Hello World!
from a running container.
Time to Solve: 15 minutes.
C’est parti pour du Docker !
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
admin@i-0d07b2079856860d3:/$ cd home/admin/app/
admin@i-0d07b2079856860d3:~/app$ ls -a
. .. .dockerignore Dockerfile package-lock.json package.json server.js
admin@i-0d07b2079856860d3:~/app$ cat .dockerignore
node_modules
npm-debug.log
admin@i-0d07b2079856860d3:~/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" ]
À première vua tout semble bon. Voyons voir s’il y a encore un conteneur présent :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
admin@i-0d07b2079856860d3:~/app$ sudo docker images -a
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> a6ee5c4d5a96 17 months ago 124MB
<none> <none> 0b18357df7c9 17 months ago 124MB
app latest 1d782b86d6f2 17 months ago 124MB
<none> <none> 5cad5aa08c7a 17 months ago 124MB
<none> <none> acfb467c80ba 17 months ago 110MB
<none> <none> 463b1571f18e 17 months ago 110MB
node 15.7-alpine 706d12284dd5 3 years ago 110MB
admin@i-0d07b2079856860d3:~/app$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
124a4fb17a1c app "docker-entrypoint.s…" 17 months ago Exited (1) 17 months ago elated_taussig
admin@i-0d07b2079856860d3:~/app$ sudo docker logs 124a4fb17a1c
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: []
Là, il fallait être attentif au détail : Node tente d’exécuter serve.js
alors que le fichier s’appelle server.js
(une lettre en plus).
On corrige le Dockerfile, on recrée l’image et on relance :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
root@i-0817bf54eaf7b54d1:/home/admin/app# docker build -t app .
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 ./* ./
---> 853722d2e8fc
Step 6/7 : EXPOSE 8880
---> Running in ef29a0a042f6
Removing intermediate container ef29a0a042f6
---> 509af769a64d
Step 7/7 : CMD [ "node", "server.js" ]
---> Running in 6c71c9461ed1
Removing intermediate container 6c71c9461ed1
---> f171ac81321b
Successfully built f171ac81321b
Successfully tagged app:latest
root@i-0817bf54eaf7b54d1:/home/admin/app# docker run -d app
be3744800d849d25d5a801c5a32f7a271d99b9b7bf02cb04620972e3bca10939
root@i-0817bf54eaf7b54d1:/home/admin/app# curl localhost:8888
these are not the droids you're looking for
Cette fois, on n’obtient pas le contenu espéré…
Le script est pourtant tout simple :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var express = require('express'),
app = express(),
port = process.env.PORT || 8888,
bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.use(function(req, res) {
res.status(404).send({url: req.originalUrl + ' not found'})
});
app.listen(port);
console.log('Server Started on: ' + port);
Ah, mais oui ! J’ai oublié de rendre le port du conteneur accessible. Actuellement le port est utilisé par un autre service :
1
2
3
4
5
6
7
8
root@i-0817bf54eaf7b54d1:/home/admin/app# ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=588,fd=3))
LISTEN 0 511 0.0.0.0:8888 0.0.0.0:* users:(("nginx",pid=608,fd=6),("nginx",pid=607,fd=6),("nginx",pid=606,fd=6))
LISTEN 0 4096 *:6767 *:* users:(("sadagent",pid=561,fd=7))
LISTEN 0 4096 *:8080 *:* users:(("gotty",pid=560,fd=6))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=588,fd=4))
LISTEN 0 511 [::]:8888 [::]:* users:(("nginx",pid=608,fd=7),("nginx",pid=607,fd=7),("nginx",pid=606,fd=7))
Actuellement, on tape sur Nginx :
1
2
root@i-0817bf54eaf7b54d1:/home/admin/app# cat /var/www/html/index.nginx-debian.html
these are not the droids you're looking for
Du coup, je stoppe Nginx et relance Docker comme il faut :
1
2
3
4
5
6
7
root@i-0817bf54eaf7b54d1:/home/admin/app# systemctl stop nginx
root@i-0817bf54eaf7b54d1:/home/admin/app# docker stop be3744800d84
be3744800d84
root@i-0817bf54eaf7b54d1:/home/admin/app# docker run -p 8888:8888 -d app
77a84a67da3fd733c38b59c5e1ea366cbf6a1b190cceaca50050ee767438b6af
root@i-0817bf54eaf7b54d1:/home/admin/app# curl localhost:8888
Hello World!