Setting up a server with multiple domains and ports
Tags: webserver, domains, docker, apache
Published: 2021-09-19 07:08:43

I wanted to use an existing webserver (running on Linode's cheapest $USD 5 / month plan) for a new project. Since I already have a domain pointing to that domain, I can't use port 80 for the new project. 

This is what my setup looks like:
- existing project: running on Apache, port 80
- new project (Vue frontend, running on Nginx in Docker container), port 8080
- new project (Laravel API backend, running on Nginx in Docker container), port 8880

## DNS record

First, I needed to setup the DNS. I like to use Cloudflare for handling my domains. What I like about Cloudflare is that not only does it protect ones website from DDos attacks and make the website load faster, it's also easy to make the switch to a different server, as one can just change the IP address in the [A record](https://www.cloudflare.com/en-gb/learning/dns/dns-records/dns-a-record/). 

## Backend API

For the Backend, I have a Dockerfile that installs stuff needed by PHP and and a docker-compose.yml file for building both the PHP and Nginx container. I'll just display the Nginx stuff. Please note that part `ports` where we expose the port `8880`:

```
version: "2.0"
services:
  #PHP Service
  #here goes configuration for PHP container

  #Nginx Service
  webserver:
    image: nginx:alpine
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "8880:80"
    volumes:
      - ./:/var/www/html/
      - ./nginx/conf.d/:/etc/nginx/conf.d/
    networks:
      - app-network

#Docker Networks
networks:
  app-network:
    driver: bridge
```
One thing to note is that I originally had used port `8000`, but that [port is not supported by Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200169156-Identifying-network-ports-compatible-with-Cloudflare-s-proxy), which is why I changed it to `8880`. 

Starting the backend service is simply done by running `docker-compose up -d` inside the backend code folder. 

## Frontend

For the frontend, I have a simple Dockerfile that runs the Vue JS code in a Docker container:

```
FROM node:latest as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build

FROM nginx as production-stage
RUN mkdir /app
COPY --from=build-stage /app/dist /app
COPY nginx.conf /etc/nginx/nginx.conf
```

The connection to the backend API is set inside the .env file:

`VUE_APP_BACKEND=http://www.domain.com:8880`

Building the container is done like this:

`docker build . -t my-app`

I don't have a `docker-compose.yml` file for the frontend, so I run this command where I expose the port 8080:

`docker run -d -p 8080:80 my-app`

## Setting up a redirect in Apache

Now everything works, but I don't want the user to have to enter the port when entering the url. E.g. when the user enters www.domain.com, it should redirect to www.domain.com:8080

In apache.conf I added the following:

```
ServerName "domain.com"
<VirtualHost _default_:80>
        ServerName "domain.com"
        ServerAlias "www.domain.com"
        RewriteEngine On
        # Redirect all requests to the local Apache server to port 8080
        RewriteRule ^.*$ http://%{HTTP_HOST}:8080%{REQUEST_URI}
</VirtualHost>
```

OK, that's all. I hope I didn't forget anything, as I wrote this so that I will remember what to do if I need to setup everything from scratch. As always, please let me know in the comments if anything could be done better...