Showing posts with label apache2. Show all posts
Showing posts with label apache2. Show all posts

Sunday, 5 July 2020

Setting up a basic reverse proxy using nginx

The aim was to achieve the following, a user will connect to machine1 running on Nginx at port 80. The Nginx will serve the files unless the URL is of the form test1 or test2, if the url is of the form test1 it will forward the request to an apache server running on the same machine at port 85. If it is of form test2/ then the request will be sent to another machine and that response will be served to the user.

Both the machines are running on Lubuntu in Vbox.

Setting up Machine1:

In machine1 Nginx was installed first
Sudo apt install nginx
Followed by Apache2
sudo apt install apache2

Now, apache2 will fail to start since Nginx is already listening on port 80. To change the listening port edit /etc/apache2/ports.conf and change the line Listen 80 to Listen 85

You must also edit /etc/apache2/sites-enabled/000-default.conf and make the following changes

  1.  <VirtualHost *: 80> should be changed as <VirtualHost *: 85>
  2. change the DocumentRoot from /var/www/html  to /var/www/html_apache
Open folder /var/www/html and CUT and paste index.html to /var/www/html_apache

If you are unable to save changes to files and get a permission error, run your text editor as sudo. If you get errors while copy-pasting index files run the file manager as root. In Lubuntu you can open a terminal and type sudo pcmanfm

Also, create an index.html inside /var/www/html_apache/test1 and include some text so that you know the response is from apache.
Restart apache with the command 
sudo service apache2 restart
Now opening Localhost should point to Nginx welcome page and localhost:85 should show the apache welcome page

Setting up Machine2:

In machine2 you can simply install apache2, no special changes are required. Get the local IP address of machine2 using the command ifconfig (mine was 192.168.1.5). Also, create an index.html inside /var/www/html/test2 and include some text 

I haven't set up PHP or database. You can do that if you want.

Setting up the reverse proxy:

To set up the reverse proxy, in machine1 you should edit the file /etc/nginx/sites-available/default (another approach will be to create a new conf file and linking it to sites-enabled, but I will be editing the default file). Find the block that says location / and at the end of that block add a new location as shown below

location /test1/ {
proxy_pass http://127.0.0.1:85;
}

This will pass any request of the form /test1/ to localhost:85/test1/ . For example, a request like /test1/apix will be forwarded to apache in machine1 as localhost:85/test1/apix

Similarly, for test2, you can just add the IP address of machine2 (if you are hosting it somewhere use its public IP) instead of the localhost address

location /test2/ {
proxy_pass http://192.168.1.5;
}

And that's it, you may also need to forward the ip address of the user to the apache servers. If not the address of the Nginx server will be recorded for each request. To do so add the headers as shown below
location /test1/ {
proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:85;
  }

You can also set the reverse proxy in such a way that all php files will be served from a particular server.







 
 

 



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.

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...