HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptdockerMinor

How not expose my backend

Submitted by: @import:stackexchange-devops··
0
Viewed 0 times
backendexposenothow

Problem

I'm studying Docker and how to properly publish my containers coding a very simple web application. It has only two containers, backend and frontend. I've published the source code here: https://github.com/sinayra/hello-private-world

If I run locally each node application, its works "fine" (everything is public, but this is not what I want in the end of the day). Then, I created Dockerfile for each container, to try to simulate a real application. For the frontend, I exposed the port 3000 to access from the host. However, I don't want to expose the port 3333 for the host, and, because of that, my front can't fetch the data from the back.

Here is my index.html from the frontend.


  
    Hello Public World
  
  
    Message from backend:
    

    
      const back = document.getElementById("backend");
      const url = "http://localhost:3333/"; //I tried backend:3333, but without success

      fetch(url)
        .then((resp) => resp.json()) // Transform the data into json
        .then(function (data) {
          back.innerHTML = data.message;
        });
    
  


Its Dockerfile:

# pull official base image
FROM node:lts

# set working directory
WORKDIR /usr/src/app

# install app dependencies
COPY package.json ./
RUN npm install

# add app
COPY . ./

EXPOSE 3000

# start app
CMD ["npm", "run", "start"]


My index.js from backend:

const express = require("express");
const app = express();
const cors = require("cors");
const port = 3333;

const allowlist = ["http://localhost:3000"];
const corsOptions = {
  origin: allowlist,
  methods: "GET",
  preflightContinue: false,
  optionsSuccessStatus: 204,
};
app.use(cors(corsOptions));

app.use(express.json());
app.get("/", (req, res) => {
  console.log("GET /");
  res.json({ message: "Hello Private World!" });
});

app.listen(port, () =>
  console.log(`Example app listening at http://localhost:${port}`)
);


Its Dockerfile:

```
# pull official base image
FROM node:lts

# set working directory
WO

Solution

The layer that you're missing is nginx proxy. See my toy Mafia Game project here how to do it:

  • Shell deployment project (uses either Docker compose or k8s) - https://github.com/taleodor/mafia-deployment



  • Vue.js frontend - https://github.com/taleodor/mafia-vue



  • Express.js backend - https://github.com/taleodor/mafia-express



  • (Optional) detailed write-up about CI/CD and how it's built from DevOps prospective - https://itnext.io/building-kubernetes-cicd-pipeline-with-github-actions-argocd-and-reliza-hub-e7120b9be870



The missing piece in your case is nginx proxy that you use in your UI.

So what you need to do is to define some location for your api - i.e. /api. Then your proxy it via nginx - see my nginx configuration for the project above here - https://github.com/taleodor/mafia-vue/tree/master/nginx. At the same time it's highly recommended for performance to deploy static resources on the same nginx.

Use Dockerfile to define environment variables and defaults, i.e. in my project - https://github.com/taleodor/mafia-vue/blob/master/Dockerfile

Finally, you can update configuration via environment variables in your docker-compose yaml or k8s definitions.

Context

StackExchange DevOps Q#11931, answer score: 2

Revisions (0)

No revisions yet.