I have created a node.js express app that calls the Docker API on the unix socket /var/run/docker.sock
Anything involving a GET request works as expected. For anything involving a POST request, the action will get carried out, but then any future requests from my app to the Docker API are answered with 404 page not found.
For example, when I send a request to start a container, the container will start successfully, but everything sent to the Docker API after that errors out with 404.
Requests made outside of the app (like with curl) continue to work, so I'm sure it's something wrong in my code.
Here is the code that I suspect is causing a problem:
app.get('/containers/:containerId/start', (req, res) => {
let containerId = req.params['containerId'];
let apiOptions = requestOptions;
apiOptions.path = `/containers/${containerId}/start`;
apiOptions.method = 'POST';
apiOptions.headers = {
'Content-Type': 'application/json',
'Content-Length': 0
};
let data = '';
const apiReq = http.request(apiOptions, (apiRes) => {
console.log(`${apiRes.statusCode} - ${apiOptions.path}`);
apiRes.on('data', d => {
data += d.toString();
});
apiRes.on('end', () => {
res.setHeader("Content-Type", "application/json");
res.send(JSON.stringify(data, null, 2));
});
});
apiReq.on('error', err => {
console.error(err)
});
apiReq.end();
});
It's pretty close to a textbook example and I have similar code doing GET requests without a problem. I am not using apiReq.write(data)
for the POST because the Docker API expects the body to be empty.
I suspect there is something waiting for a connection to be closed and that I'm missing a line of code that would do that.
Here's a sample of some logging of the response codes for the various API requests and also extra logging info for the post request that causes the app to hang:
Listening on 0.0.0.0:8088.
200 - /images/json
200 - /containers/json?all="true"
{
"socketPath": "/var/run/docker.sock",
"path": "/containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Content-Length": 0
}
}
204 - /containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start
404 - /containers/json?all="true"
404 - /images/json
The 204 response from the POST indicates success according to the API Doc and I can see the container has started. But the app never recovers. I have to kill it and restart.
Any idea what I'm missing that's causing my app to hang on POST requests?
EDIT:
I have isolated the code that calls the Docker API in a separate program with a simple, 30 second setInterval() loop. Interestingly, it is working fine. I can stop the container (using a docker stop
on command-line) and the POST request in my loop successfully starts it again.
Here's the code I'm testing with:
const http = require('http');
var containerId = '75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297';
var options = {
socketPath: '/var/run/docker.sock',
path: `/containers/${containerId}/start`,
method: 'POST'
};
setInterval(() => {
let data = '';
const apiReq = http.request(options, (apiRes) => {
apiRes.on('data', d => {
data += d.toString();
});
apiRes.on('end', () => {
console.log(`${apiRes.statusCode} - ${options.path}`);
console.log(JSON.stringify(data, null, 2));
});
});
apiReq.on('error', err => {
console.error(err)
});
apiReq.end();
}, 30000);
Here's the console.log() output:
204 - /containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start
""
304 - /containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start
""
304 - /containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start
""
204 - /containers/75b4ebdb7879e9cc9af134f63b4a02b2a218f52376fa377d89f5e384fdf78297/start
""
The 204 responses indicate the API successfully started the container. The 304 responses indicate there was nothing for the API to do, since the container was already running.
In short, the API call works fine outside of the express.js route I have the original code wrapped up in. I am now suspecting my problems lie with the way I have that configured.