Wednesday, 25 December 2019

Packaging apache in a container

Now that I have installed Docker. I decided to try to create an image for apache2. I found some references here. So this is how it works, I create a file called dockerfile and put in a series of commands docker will use the commands to create the image from which the container could be created. I would need a base image on which apache2 can be installed. Some googling around I found that alpine is the preferred base image due to its smaller size but I decided to stick with ubuntu. Based on the documentation, I guess, I would need to use commands like FROM, RUN, EXPOSE and CMD/ENTRYPOINT in my dockerfile.
I created a folder called DockerTesting and a subfolder apache2 inside which I created a file called dockerfile with the following content

FROM ubuntu
RUN ["apt-get","update"]
RUN ["apt-get","install","apache2","-y"]
EXPOSE 80
ENTRYPOINT systemctl start apache2.service

My understanding is that the FROM command retrieves a base image, in this case, a slimmed-down version of ubuntu. The RUN command runs the commands in the base image like 'apt-get install apache2 -y' will install apache2 in the ubuntu image I had. The EXPOSE command exposes a port of the ubuntu image outside the container. In this case, I am exposing port 80 since apache serves http requests at port 80 (and I  didn't plan on implementing https for now). The ENTRYPOINT command runs the command once the container starts to run. I think I could have used the CMD command also and got a similar result but the documentation seems to prefer this method especially since we can pass parameters to apache this way. Now everything seems fine why don't we create the image and build the container. These commands require sudo to run each time hence I ran 'sudo su' at the start so that I don't have to use sudo each time. I 'cd' into DockerTesting/apache2 and used the following command to build the image

docker build -t apache2

and ended with the following error '"docker build" requires exactly 1 argument.' and also 'Usage:  docker build [OPTIONS] PATH | URL | -'. So it requires a path. It took me some time to realize I missed a dot at the end

docker build -t apache2 .

So if I am in the directory as the docker file I need to use a dot at the end or ./path. Now the image got created. And I could verify it using the command 'docker images'


docker images command

Got confused seeing the ubuntu image at first but a google search cleared it up. It is just the base image I built the image on top of. Now to create the container, I used the following command to create the container

docker run -p 100:80 --name apachecontainer apache2

I mapped the port 80 of the container to the port 100 of my machine. So that I could access apache server at http://localhost:100 and gave a fancy name for my container too. But on running the command I got an error "/bin/sh: 1: systemctl: not found". What is this, it seems the base ubuntu image does not have systemctl installed. So either I have to install systemctl while creating the image or find another way to start apache2 (I found a few ways here). I used the second approach, I decided to use apache2ctl instead of systemctl. And to fix it I will have to rebuild the image and then create the container.
Running the command 'docker ps -a' will show that the container 'apachecontainer' was created but didn't run. First I want to remove the faulty image apache2 before changing my dockerfile. But to remove the image I have to remove the container that uses the image. I did it by running the following commands

docker rm apachecontainer
docker rmi apache2            

Now I made the following changes to the dockerfile
FROM ubuntu
RUN ["apt-get","update"]
RUN ["apt-get","install","apache2","-y"]
EXPOSE 80
ENTRYPOINT apache2ctl start
Now I built the image and created the container

docker build -t apache2 .                                            
docker run -p 100:80 --name apachecontainer apache2

This time I got the following output. "AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message". This is just a warning and apache should have started. But I couldn't access it at http://localhost:100. What now, running "docker ps -a" shows the following


The server started but was shutdown immediately. A google search revealed that the process should run in foreground or else the container gets shutdown. The solution is to run a the program in the foreground or use a command that doesn't end like 'tail -f /dev/null'. So I changed my dockerfile as

FROM ubuntu
RUN ["apt-get","update"]
RUN ["apt-get","install","apache2","-y"]
EXPOSE 80
ENTRYPOINT apache2ctl start && tail -f /dev/null 

Now recreate the image and run

docker rm apachecontainer
docker rmi apache2
docker build -t apache2 .      
docker run -p 100:80 --name apachecontainer apache2

And this time I was able to access apache at http://localhost:100.


Now there is only one thing I need to do. Access and change the apache default page and add my own pages. To do that I need to use the -v parameter while running (as given here) I also found that the -d parameter runs the container in the background and so will get detached from the terminal. So removed the container and ran it again

docker rm apachecontainer
docker run -d -v  /home/user/Desktop/DockerTesting/htmlFiles:/var/www/html -p 100:80 --name apachecontainer apache2


Here I have linked the folder /DockerTesting/htmlFiles to the folder /var/www/html in the container. So now apache will be serving the files from /DockerTesting/htmlFiles. To verify I placed an index.html file in that location and tried to access http://localhost:100, and this is what I got


I also learned the following. To stop the container I can use

docker stop apachecontainer

and most importantly, to restart the container I should not use the run command again but rather the start command

docker start apachecontainer

So I guess I have installed apache2 in a container successfully. Next, I plan to install php. I want to install it in a separate container and link it with this container but not sure if it is possible or I would have to install it in the same container as apache. I will try it out and post about it.

No comments:

Post a Comment

Setting GitHub hooks in Jenkins

While setting up a Freestyle project in Jenkins we may need to set Github webhooks in Jenkins so that Jenkins will get notified each time th...