Docker/Compose: Define and use env variable - apache

on my github i'm creating a little fork from a debian minimal docker image. Its actually 5 packages which build up on previous:
debian-base-minimal
debian-base-standard
debian-base-security
debian-base-apache
debian-base-apache-php
On debian-base-apache i want to get a working env variable, which i can define later in docker-compose file. What should the env do?
Its should, if defined over docker-compose, write ServerName $SERVER_NAME at the end of /etc/apache2/apache2.conf to set a globally Server Name. If empty, no new line should be written.
But why its should write nothing when its empty? Cauz on build the Dockerfile to an image shouldnt include the SERVER_NAME.
I already tried something like:
echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
on my 040-debian-base-apache file. But on build its wrote ServerName in, cauz i didnt defined a value and its using null. If i set a default in Dockerfile (ENV SERVER_NAME=127.0.0.1) its build the image with 127.0.0.1 and i cant change 127.0.0.1 via variable, cauz the variable already filled in with the value.
On ouput of the building with defined ENV SERVER_NAME=127.0.0.1 in Dockerfile (actually not in repo):
[...]
+ echo 'ServerName 127.0.0.1'
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
ok.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2.
ok.
[...]
Its would be okay, if there stands default 127.0.0.1 cauz the apache can start. But i cant define it now in docker-compose.yml cauz its hardcoded 127.0.0.1 and not the output of a variable.
On ouput of the building with none defined ENV in Dockerfile (actually repo version):
[...]
+ echo 'ServerName '
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2 failed!
The apache2 configtest failed. ... (warning).
Output of config test was:
AH00526: Syntax error on line 228 of /etc/apache2/apache2.conf:
ServerName takes one argument, The hostname and port of the server
[...]
Can anybody help me to get this working? Would be nice to understand how it works.
Many thanks in advance.

As you've observed, every RUN command in the Dockerfile happens at docker build time, and in particular the contents of the file will be fixed based on what the environment variable was when you ran the build. You want it to change based on the runtime value of the variable, which means you need to write a script that runs at startup to do this.
A typical approach is to write an ENTRYPOINT script that does the first-time setup. The ENTRYPOINT gets passed the CMD (or whatever command got passed into docker run) as command-line arguments, so if it ends with exec "$#", the last thing it does is launch the "normal" command. You can use any ordinary shell script logic here, so I might write
#!/bin/sh
if [ -n "$SERVER_NAME" ]; then
echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
fi
exec "$#"
Then you can provide this in your Dockerfile
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["apachectl", "-DFOREGROUND"]
(The chmod isn't necessary if you can guarantee the file has execute permissions on your non-Windows host. The ENTRYPOINT must use the JSON-ish form. If you have another image that builds on top of this, remember that the combined image gets only one ENTRYPOINT and one CMD; the very deep stack of images you suggest is a pretty unusual setup.)

Related

Set host ip in run parameters Intellij with WSL2

I have a run configuration setup for a server tool. I want to run it in WSL2 environment from an Intellij run task. This works great but I need to manually set the Windows host IP whenever I restart the WSL2. To get the host IP I want to use this grep command:
grep -o -P "(?<=nameserver )[0-9\.]+" /etc/resolv.conf
I played with the configuration and tried something like this
This didn't work, because the grep command didn't get executed. It worked as expected when I used it in the console.
Trying the same thing with the enviroment variable didn't succeed as well.
I saw that it is possible to setup a "before run task". Maybe it is possible to do it with this option?

Docker ADD and COPY not honored in Dockerfile

When I try to build the following Dockerfile, the ADD and COPY steps do nothing:
# Use an official Apache runtime as a parent image
FROM amd64/httpd
# Set the working directory
WORKDIR /usr/local/apache2
# Copy the following contents into the container
ADD ./httpd.conf {$workdir}/conf/httpd.conf
COPY ./Projects/RavensHomeSupport/build/* {$workdir}/htdocs/Test/
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME RavensHomeWeb
I run the following build command:
docker build -t ravenshome --rm --no-cache .
and when I check the contents of the Test directory in the running container, none of the data that I expected has been copied across to the container. The output of the build command is here.
Sending build context to Docker daemon 1.444MB
Step 1/6 : FROM amd64/httpd
---> 19459a872194
Step 2/6 : WORKDIR /usr/local/apache2
---> Running in 192cb44f767e
Removing intermediate container 192cb44f767e
---> d9816ea17258
Step 3/6 : ADD ./httpd.conf {$workdir}/conf/
---> 19f48db970bb
Step 4/6 : COPY ./Projects/RavensHomeSupport/build/ {$workdir}/htdocs/Test/
---> d93939218c2b
Step 5/6 : EXPOSE 80
---> Running in 43b9e9297f60
Removing intermediate container 43b9e9297f60
---> 3b994be07747
Step 6/6 : ENV NAME RavensHomeWeb
---> Running in a64bccaf81c8
Removing intermediate container a64bccaf81c8
---> 9217c242868c
Successfully built 9217c242868c
Successfully tagged ravenshome:latest
I start the container with the following command:
docker run -dit -p 8080:80 --name ravenshome ravenshome
When I examine the problem directory in the container with the following command:
docker exec ravenshome ls -a /usr/local/apache2/htdocs
I get the following result:
.
..
index.html
As you can see, all that was there is the contents of the default image, not the additional content that I expected.
Similarly, my customized version of httpd.conf is not copied to the new container.
I have read several posts that suggest that the problem is due to using volumes, but I am not doing so, nor do I have a .dockerignore file.
Can anyone see what I am doing wrong?
$workdir isn't a defined environment variable, so it expands to an empty string. $variable inside curly braces isn't special syntax at all; it expands to the variable expansion, inside curly braces. The net result of this is that these two lines:
WORKDIR /usr/local/apache2
ADD ./httpd.conf {$workdir}/conf/httpd.conf
copy content into a directory /usr/local/apache2/{}/conf/http.conf -- nothing is inside the curly braces, and the curly braces themselves are interpreted as a directory relative to the current working directory.
You don't need an environment variable here at all; you can just COPY to the current WORKDIR
WORKDIR /usr/local/apache2
ADD ./httpd.conf ./conf/httpd.conf
COPY ./Projects/RavensHomeSupport/build/* ./htdocs/Test/
See also Variable substitution in the docker-compose.yml documentation for the allowed forms; you're probably thinking of ${variable} syntax (dollars outside the curly braces).

Why httpd container stop working on restart of system?

On a fresh installation of httpd and PHP images and container get to create and work fine. But on restart of my system, httpd stop working. It's not able to find the docroot folder. So is there any setting we need to do for same.
Throw error:
AH00112: Warning: DocumentRoot [/var/www/html/docroot/] does not exist docker error
From the documentation:
Use a restart policy To configure the restart policy for a container,
use the --restart flag when using the docker run command. The value of
the --restart flag can be any of the following:
https://docs.docker.com/config/containers/start-containers-automatically/
You have to start your container in daemon mode:
docker run -d hello-world

How do I call a local shell script from a web server?

I am running Ubuntu 11 and I would like to setup a simple webserver that responds to an http request by calling a local script with the GET or POST parameters. This script (already written) does some stuff and creates a file. This file should be made available at a URL, and the webserver should then make an http request to another server telling it to download the created file.
How would I go about setting this up? I'm not a total beginner with linux, but I wouldn't say I know it well either.
What webserver should I use? How do I give permission for the script to access local resources to create the file in question? I'm not too concerned with security or anything, this is for a personal experiment (I have control over all the computers involved). I've used apache before, but I've never set it up.
Any help would be appreciated..
This tutorial looks good, but it's a bit brief.
I have apache installed. If you don't: sudo apt-get install apache2.
cd /usr/lib/cgi-bin
# Make a file and let everyone execute it
sudo touch test.sh && chmod a+x test.sh
Then put the some code in the file. For example:
#!/bin/bash
# get today's date
OUTPUT="$(date)"
# You must add following two lines before
# outputting data to the web browser from shell
# script
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Demo</title></head><body>"
echo "Today is $OUTPUT <br>"
echo "Current directory is $(pwd) <br>"
echo "Shell Script name is $0"
echo "</body></html>"
And finally open your browser and type http://localhost/cgi-bin/test.sh
If all goes well (as it did for me) you should see...
Today is Sun Dec 4 ...
Current directory is /usr/lib/cgi-bin Shell
Shell Script name is /usr/lib/cgi-bin/test.sh

How to shorten an inittab process entry, a.k.a., where to put environment variables that will be seen by init?

I am setting up a Debian Etch server to host ruby and php applications with nginx. I have successfully configured inittab to start the php-cgi process on boot with the respawn action. After serving 1000 requests, the php-cgi worker processes die and are respawned by init. The inittab record looks like this:
50:23:respawn:/usr/local/bin/spawn-fcgi -n -a 127.0.0.1 -p 8000 -C 3 -u someuser -- /usr/bin/php-cgi
I initially wrote the process entry (everything after the 3rd colon) in a separate script (simply because it was long) and put that script name in the inittab record, but because the script would run its single line and die, the syslog was filled with errors like this:
May 7 20:20:50 sb init: Id "50" respawning too fast: disabled for 5 minutes
Thus, I got rid of the script file and just put the whole line in the inittab. Henceforth, no errors show up in the syslog.
Now I'm attempting the same with thin to serve a rails application. I can successfully start the thin server by running this command:
sudo thin -a 127.0.0.1 -e production -l /var/log/thin/thin.log -P /var/run/thin/thin.pid -c /path/to/rails/app -p 8010 -u someuser -g somegroup -s 2 -d start
It works apparently exactly the same whether I use the -d (daemonize) flag or not. Command line control comes immediately back (the processes have been daemonized) either way. If I put that whole command (minus the sudo and with absolute paths) into inittab, init complains (in syslog) that the process entry is too long, so I put the options into an exported environment variable in /etc/profile. Now I can successfully start the server with:
sudo thin $THIN_OPTIONS start
But when I put this in an inittab record with the respawn action
51:23:respawn:/usr/local/bin/thin $THIN_OPTIONS start
the logs clearly indicate that the environment variable is not visible to init; it's as though the command were simply "thin start."
How can I shorten the inittab process entry? Is there another file than /etc/profile where I could set the THIN_OPTIONS environment variable? My earlier experience with php-cgi tells me I can't just put the whole command in a separate script.
And why don't you call a wrapper who start thin whith your options?
start_thin.sh:
#!/bin/bash
/usr/local/bin/thin -a 127.0.0.1 -e production -l /var/log/thin/thin.log -P /var/run/thin/thin.pid -c /path/to/rails/app -p 8010 -u someuser -g somegroup -s 2 -d start
and then:
51:23:respawn:/usr/local/bin/start_thin
init.d script
Use a script in
/etc/rc.d/init.d
and set the runlevel
Here are some examples with thin, ruby, apache
http://articles.slicehost.com/2009/4/17/centos-apache-rails-and-thin
http://blog.fiveruns.com/2008/9/24/rails-automation-at-slicehost
http://elwoodicious.com/2008/07/15/nginx-haproxy-thin-fastcgi-php5-load-balanced-rails-with-php-support/
Which provide example initscripts to use.
edit:
Asker pointed out this will not allow respawning. I suggested forking in the init script and disowning the process so init doesn't hang (it might fork() the script itself, will check). And then creating an infinite loop that waits on the server process to die and restarts it.
edit2:
It seems init will fork the script. Just a loop should do it.