'Executing a startup script when docker container is up
I built a docker image with Dockerfile as below. Everything's okay except but RUN php /var/www/api/startup.php This PHP code is simple, just an API request to get some data from outside server.
When I run this image, it works well but I get into the container and see the created file:ocr_url.json.. saying "error!!!".
When I run the php code in docker container in person, it works fine. So I checked the ENV variable: $SERVER. it returns "server-1" that I set in docker-compose.yml.
What's wrong? Does it execute PHP code before I get the ENV variable? Please help me through this problem. thanks
<?php
//echo $server = $_ENV['SERVER'];
$server = getenv('SERVER');
if($server) {
$url = "https://{url}/?server=$server";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
//for debug only!
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$resp = curl_exec($curl);
curl_close($curl);
//save to json file
$file = fopen("ocr_url.json","w");
fwrite($file, $resp);
fclose($file);
}
else {
$file = fopen("ocr_url.json","w");
fwrite($file, 'error!!!');
fclose($file);
}
Dockerfile
FROM server:v1.0
#startup program
CMD /root/startup.sh
RUN php /var/www/api/startup.php
WORKDIR /var/www/api
docker-compose.yml
version: '3.8'
services:
server1:
image: '5318a9bfda5e'
stdin_open: true
tty: true
ports:
- '127.0.0.1:7771:80'
environment:
- 'SERVER=server-1'
server2:
image: '5318a9bfda5e'
stdin_open: true
tty: true
ports:
- '127.0.0.1:7772:80'
environment:
- 'SERVER=server-2'
Solution 1:[1]
Despite the order you have things in the Dockerfile, a RUN command always runs during the image build sequence, not at container startup, and it can never call out to other services. It also doesn't get to see Compose environment: settings or anything else outside a build: block. Whatever the output of the RUN command is will get compiled into the image, and since you're running the same image for both containers, they'll have the same downloaded file.
An entrypoint wrapper script might be a good match for this setup. When the container starts, make its main process be a script that first does the download from the other container, then runs the standard container CMD. The script could look like:
#!/bin/sh
# Download the file from elsewhere
php /var/www/api/startup.php
# (or consider writing it as a half-dozen lines of shell code)
# Run the main container process (from the Dockerfile CMD for example)
exec "$@"
Then in your Dockerfile, COPY this script in and make it be the ENTRYPOINT.
FROM server:v1.0
WORKDIR /var/www/api
# COPY entrypoint.sh . # from the base image?
# RUN chmod +x entrypoint.sh # Docker preserves permissions from the host
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array form
CMD /root/startup.sh # unmodified from original Dockerfile
The file won't get downloaded during the image build, but if you launch a debugging shell
docker-compose run server1 sh
you will it will first download the file via the entrypoint script before launching the sh command.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | David Maze |
