How to build a webservice with docker

To start building a new Service, you’ll need an image first.
Our Service will be an apache Server which delivers an application.

So get an image from dockerhub or build your own (as described in my last post).

We’ll start by creating a working directory for our files:

mkdir docker_perl_hello_world 
cd docker_perl_hello_world

Let’s add a simple Perlscript, that prints “Hello World!” (I had this lying around already, but use whatever language you prefer).

vi mywebsite/index.pl

#!/usr/bin/perl print "Content-type: text/html\n\n"; 
print <<HTML; 
<html> 
 <head> 
  <title>Simple Perl Script</title> 
 </head> 
  <body> 
   <h1>Perl says:</h1> 
   <p>Hello World!</p> 
  </body> 
HTML 
exit;

don’t forget to make this executable

chmod +x mywebsite/index.p

Now, let’s create a simple vhost config for apache, so that it knows what to do with our script:

vi 001-perlcgi.conf

<VirtualHost *:80>
      ServerName localhost      
      DocumentRoot /var/www/html/        
        <Directory "/var/www/html/perl">
                  AllowOverride None
                  Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                  Order allow,deny
                  Allow from all
                  AddHandler cgi-script .pl
        </Directory>
      ErrorLog /var/log/apache2/perlcgi-error.log
      CustomLog /var/log/apache2/perlcgi-access.log combined
 </VirtualHost>

this is the heart of our build and requires some explanation:

vi Dockerfile

# Dockerfile for Apache Server 
FROM stretchbase:latest 
LABEL maintainer "nkalle@nikster.de" 
Label description "Apache Webserver with perl cgi" 

# install Apache and remove unneeded data 
RUN apt-get update && apt-get install -y apache2 libapache2-mod-perl2 && apt-get -y clean && rm -rf /var/cache/apt /var/lib/apt/lists/* 

# copy the vhost definition for our service 
COPY 001-perlcgi.conf /etc/apache2/sites-available/ 

# enable the default and the perl-script page 
RUN a2ensite 001-perlcgi 
RUN a2enmod cgi 
EXPOSE 80 

#copy the script to its destination 
RUN mkdir /var/www/html/perl 
COPY mywebsite/ /var/www/html/perl 
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

We have created the Dockerfile, this contains all the information the Docker daemon needs to assemble our new container, and within it, our service.

“FROM” tells docker which baseimage it should use (in this case the image that we built in the last post).
“LABEL” adds additional info.
The “RUN” Keyword allows us to run all kinds of commands inside the conatiner, thus configuring it.
Here, I’m updating the apt repo information, so that the latest version of apache and libapache-mod-perl2 can be installed.
Afterwards I’m cleaning up, to keep the Image as small as possible.
Now we’ll “COPY” our vhost.conf to the right place. And then enable it and the cgi Module with the “RUN” Keyword.
“EXPOSE” tells docker which port to expose (with apache that’s usually 80 and/or 443), this can be mapped to what you like later.
Last we have “CMD”, which is pretty much the same as “ENTRYPOINT” to my understanding. It tells the container which command to execute (we’ll run apache).
The Syntax is important here.

It’s time to assemble our new conatiner:

docker build -f Dockerfile -t apacheperl .

docker build -f tells Docker to use this File in particular and -t tells it to immediately tag the image after the build (last post we did this in a separate step).

After a few minutes the build should be finished and you should see your new container with:

docker image ls
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
apacheperl              latest              57b87ae05e5a        24 minutes ago      361MB

Now, run it with:

docker run -d --name "apache-perl-test" --network test-net -p 8082:80 apacheperl

And then access it via:

http://localhost:8082/perl/index.pl

You have build a containerized web service!


Remark on Service start: there are more convenient way to bring up and maintain your service with docker compose or kubernetes for example.


Remark on the Dockerfile:
If we would be using official images, we could do some of the configuration, that we put into the vhost definition, via “ENV” Variables.
“ENV” are environment variables one can use to configure some aspects of the container. The only way I found to lookup all possible variables of an image, is to check out it’s documentation on dockerhub (in this case: mariadb).
One can set ones own environment variables at buildtime, using ARG, they van be accessed by ENV then

ENV APACHE_RUN_USER=www-data \    
APACHE_RUN_GROUP=www-data \
APACHE_LOG_DIR=/var/log/apache2 

Leave a comment

Your email address will not be published. Required fields are marked *