4

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.

<html>
  <head>
    <title>Hello Public World</title>
  </head>
  <body>
    <h1>Message from backend:</h1>
    <p id="backend"></p>
&lt;script&gt;
  const back = document.getElementById(&quot;backend&quot;);
  const url = &quot;http://localhost:3333/&quot;; //I tried backend:3333, but without success

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

</body> </html>

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

WORKDIR /usr/src/app

install app dependencies

COPY package.json ./ RUN npm install

add app

COPY . ./

#EXPOSE 3333

start app

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

And the Docker compose file

version: "3.8"
services:

backend: image: helloworld-private build: context: ./backend dockerfile: Dockerfile working_dir: /usr/src/app container_name: "express_container" volumes: - ./backend/:/usr/src/app - /usr/src/app/node_modules networks: - webappnetwork expose: - "3333"

web: image: helloworld-public build: context: ./web dockerfile: Dockerfile working_dir: /usr/src/app container_name: "liveserver_container" links: - backend volumes: - ./web/:/usr/src/app - /usr/src/app/node_modules environment: - PORT=3000 networks: - webappnetwork ports: - "3000:3000"

networks: webappnetwork: driver: bridge

Is there any abstraction layer that I'm missing?

Sinayra
  • 43
  • 3

1 Answers1

2

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

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.

taleodor
  • 945
  • 7
  • 11