2
votes

I'd like to containerise a client-server project I've been working on. The project structure is as follows:

├── client
│   ├── dist
│   ├── node_modules
│   ├── public
│   └── src
├── nginx
└── server
    ├── __pycache__
    ├── env
    ├── static
    └── templates

The client is a VueJs app and the server is Flask. I know I should build the Vue app using npm run build and "somehow" copy the dist folder content into the server static and templates directories. In addition I'd like to put the server behind uwsgi and Nginx for production. I've followed this tutorial:

https://pythonise.com/series/learning-flask/building-a-flask-app-with-docker-compose

but it doesn't address how to serve the static Vue files (after they've been built). I did like the approach of using docker-compose (as the tutorial suggested) so I've followed it and now I have a docker-compose.yml in the root directory and 2 Dockerfile (for client and server)

The docker-compose.yml content is:

version: "3.7"

services:

  flask:
    build: ./server
    container_name: flask
    restart: always
    expose:
      - 8080

  nginx:
    build: ./client
    container_name: nginx
    restart: always
    ports:
      - "80:80"

The server Dockerfile:

# Use the Python3.7.2 image
FROM python:3.7.2-stretch

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app 
ADD . /app

# Install the dependencies
RUN pip install -r requirements.txt

# run the command to start uWSGI
CMD ["uwsgi", "app.ini"]

app.ini content:

uwsgi]
wsgi-file = app.py
callable = app
socket = :8080
processes = 4
threads = 2
master = true
chmod-socket = 660
vacuum = true
die-on-term = true

client Dockerfile:

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

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

I thought maybe using shared volume between containers is a possible solution, but wasn't sure exactly if that's the way to go.

Any help will be greatly appreciated.

1

1 Answers

2
votes

Since you are using Vue.js I would assume that you are developing a single page application which the server (Flask) is an API server.

To serve Vue.js application using Nginx, you have to change nginx.conf instead of proxy pass to Flask, serve the static files which is /usr/share/nginx/html:

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }
}

To make Vue.js application can access API server you can proxy pass for some prefixed path such as /api to Flask:

server {
    ...

    location /api/ {
        include uwsgi_params;
        uwsgi_pass flask:8080;
    }
}