I'm rebuilding my network stack for my little intranet, and the first thing out of the gate is the HTTPd web service. So, let's get started.
I'm not using NginX because there will be a lot more CGI, and also because I want to implement my template mechanism, a custom module for the Apache HTTPd serer. Converting from an existing HTTPd configuration is a bit more difficult when it comes to migrating it in to Docker.
Now, RedHat and other Linux vendors/distributors love to part the httpd.conf file out into a whole lot of directories.
Docker doesn't do that. However, we have a little secret. So, let's create our docker image first. Create your docker directory and then the container for this specific image.
mkdir -p /opt/docker/httpd
Because the docker image is actually based on a Debian version, and because it includes an httpd.conf file already (by default), we only need three files in this directory.
For the httpd.conf, I found it easier to grab the httpd.conf file out of the docker image first, then add my custom module. And, since I wanted the image to serve content from the NAS, I needed to get the web content from that mounted up. Let's grab a copy of the docker container httpd.conf file.
docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf > httpd.conf
Now, with that, I can add my own module using the LoadModule with any custom directives. Then, we simply add the NFS mounts for the mount the NAS up via NFS, and then use volumes, too. Enter the docker compose.
services:
web:
image: httpd:2.4
container_name: httpd
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /opt/docker/storage/http/html:/usr/local/apache2/htdocs/:ro
- /opt/docker/storage/http/cgi-bin:/usr/local/apache2/cgi-bin/:ro
- /opt/docker/storage/http/logs:/usr/local/apache2/logs/:rw
- ./certs:/etc/apache2/ssl
- ./httpd.conf:/usr/local/apache2/conf/httpd.conf:ro
- ./mod_template.so:/usr/local/apache2/modules/mod_template.so:roThe container name/image, are fairly inconsequential - you can name them anything you want. The default is "apache_service" for this from the Docker image, but I like to get very specific because Apache likes to do a lot of services.
The "restart" line is there in case the EliteDesk hardware loses power and reboots - I want this container to start back up immediately.
The ports are very easy to understand if you are used to TCP. It is formatted as "HOST PORT:CONTAINER PORT".
Also, we need to set up SSL (note we have port 443 in there). Create a certificate :
mkdir certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout certs/httpd.key -out certs/httpd.crt -subj "/C=US/ST=Idaho/L=Boise/O=SilverHawk/CN=silverhawk.net"You will need to set up the standard VirtualHost for it (make sure you uncomment the LoadModule line for the ssl extension while in there) :
<VirtualHost *:443>
DocumentRoot "/usr/local/apache2/htdocs"
#ServerName www.example.com
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/httpd.crt
SSLCertificateKeyFile /etc/apache2/ssl/httpd.key
</VirtualHost>While I was there, I also added proxy and proxypass information for Grafana, (that's coming - note you need to enable xml2enc_module, proxy_http_module, and proxy_module, and make sure you disable proxy for everything except your own proxt so that someone doesn't suddenly use your site as a personal proxy to mask what they are doing on the Internet).
A grafana note :
I really strugged with proxy pass in this situation. all of the AI engines kept telling me things that were not accurate. So, here's what I have. In my httpd.conf for docker, I have the following excerpt :
ProxyRequests Off
<VirtualHost *:443>
DocumentRoot "/usr/local/apache2/htdocs"
#ServerName www.example.com
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/httpd.crt
SSLCertificateKeyFile /etc/apache2/ssl/httpd.key
RewriteEngine On
RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
RequestHeader set X-WEBAUTH-USER "%{REMOTE_USER}e"
ProxyPreserveHost On
ProxyPass /grafana/ http://172.17.0.1:3000/
ProxyPassReverse /grafana/ http://172.17.0.1:3000/
RequestHeader unset Accept-Encoding
<Location /charts>
TemplateEnabled off
</Location>
</VirtualHost>Then, in my Grafana docker-compose.yml file, I had to add the GF_SERVER_ROOT_URL and GF_SERVER_ENFORCE_DOMAIN environment variables (there are some others, to set up anonymous browsing since this will be front-ended by an authentication later) :
environment:
- GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana/
- GF_SERVER_ENFORCE_DOMAIN=false
- GF_AUTH_PROXY_ENABLED=true
- GF_AUTH_PROXY_HEADER_NAME=X-WEBAUTH-USER
- GF_AUTH_PROXY_HEADER_PROPERTY=username
- GF_AUTH_PROXY_AUTO_SIGN_UP=trueVolumes are where the magic happens for the custom module and configuration as well as the web root. Each row represents a specific file/directory that is mapped from the docker image. For example, I have my mod_template.so in there so it gets mapped into the container, plus I am mapping an httpd.conf file, as well as two NFS directories so I don't have to restart the docker every time I change the website.
Then, it's simply a matter of launching it up.
sudo docker compose up -d
Note, if you run into errors, you can use (and there is a -f option to tail -f them) :
docker compose logsThis will dump the containers log files (I suppose you COULD re-map log files if you want those pulled out of the image naturally, but this was easier).


No comments:
Post a Comment