Reputation: 2881
I've a REST Service written in C++ which has an endpoint for localhost:somePort/health. The port is configured in a yaml based config file.
I've created a script which extracts the port from the yaml file. But my problem is to assign the result to the HEALTHCHECK command in my Dockerfile.
So let's say I have a script /app/get_port.sh echoing the actual port used on startup. How do I pass that port to the HEALTHCHECK command? For example to make this work:
HEALTHCHECK --interval=10s --timeout=4s CMD curl -f "http://localhost:$MY_PORT/health" || exit
Upvotes: 5
Views: 3945
Reputation: 540
${PORT}
- no workarounds neededTo reference an environment variable in a Dockerfile
, just use wrap it inside a ${…}
and for then the runtime value is used e.g. for the healthcheck.
You can also set a default like this ${PORT:-80}
I don't remember where I saw/read this. But it works :)
So my Dockerfile
looks like this
FROM node:lts-alpine
RUN apk add --update curl
ENV NODE_ENV production
ENV HOST '0.0.0.0'
EXPOSE ${PORT:-80}
# Other steps
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost:${PORT}/health || exit 1
CMD ["node", "server.js"]
Upvotes: 4
Reputation: 128
I found that you can do this inline with a little bit of parsing.
redis:
image: 'docker.io/library/redis'
command: 'redis-server --requirepass "password"'
environment:
REDIS_HOST_PASSWORD: 'password'
healthcheck:
test: 'redis-cli -a "$$(env | grep REDIS_HOST_PASSWORD | cut -d = -f2-)" ping'
Upvotes: 0
Reputation: 11
Mine was a node app, which i needed to pass a base url path into from the docker-compose.yaml file. So did this with a separate healthcheck.js file.
Dockerfile
HEALTHCHECK --interval=10s --timeout=5s --retries=3 --start-period=15s CMD node healthcheck.js > /dev/null || exit 1
healthcheck.js
var http = require("http");
const BASEPATH = process.env.BASEPATH || "/";
var options = {
host : "127.0.0.1",
port: 3000,
path: BASEPATH,
timeout : 2000
};
var request = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
if (res.statusCode == 200) {
process.exit(0);
}
else if (res.statusCode == 301) {
process.exit(0);
}
else if (res.statusCode == 302) {
process.exit(0);
}
else {
process.exit(1);
}
});
request.on('error', function(err) {
console.log('ERROR',err);
process.exit(1);
});
request.end();
docker-compose.yaml
posterr:
image: petersem/posterr:dev
container_name: posterr
restart: unless-stopped
ports:
- "9876:3000"
volumes:
- /c/docker/posterr/randomthemes:/randomthemes
- /c/docker/posterr/config:/usr/src/app/config
environment:
- TZ=Australia/Brisbane
- BASEPATH=/mypath
Upvotes: 1
Reputation: 2881
The workaround was for me to use a subshell within the curl command:
RUN echo "Healthcheck port: $(/app/get_port.sh)\n"
HEALTHCHECK --interval=10s --timeout=4s CMD curl -f "http://localhost:$(/app/get_port.sh)/health" || exit 1
Though I wish Docker would get advanced options for handling ENV.
Upvotes: 1