Motivation: In this article, we will build a bunch of Docker containers and go step by step through the process of building the chat SPA (single page application) with the basic authorization. We will use:
cd ~
git clone git@github.com:v-kolesov/vue-sanic-spa.git
cd vue-sanic-spa
docker-compose up -d
and run a browser with the http://localhost.
cat /etc/os-release | grep PRETTY_NAME && \
docker -v && docker-compose -v && \
git --version && \
make -v
return:
PRETTY_NAME=”Ubuntu 18.04.2 LTS”
Docker version 18.09.2, build 6247962
docker-compose version 1.23.2, build 1110ad01
git version 2.17.1
GNU Make 4.1
Our application should work on http://localhost. There are 4 main routing rules:
#!/bin/bash
git init vue-sanic-spa;
cd vue-sanic-spa;
# Create .gitignore
touch .gitignore;
# and add some instructions to it
echo '.*' >> .gitignore
echo '!/.gitignore' >> .gitignore
echo '!/.env' >> .gitignore
# Create directory ".data". We will store PostgreSql and Redis database files there
mkdir .data;
# Create directory api. Here will be code of API
mkdir api;
# in directory app we'll place front-end part (VueJs)
mkdir app;
# Создаем файл переменных окружения
mkdir ws;
# also we need "nginx" directory for server.conf
mkdir nginx;
# also we need file .env,
touch .env;
# and docker-compose.yml
touch docker-compose.yml;
In stage 1 we have just created the empty .env. So fill it with default environment variables. When we will build container we pass all those variables into all of them.
ADMINER_DEFAULT_SERVER=pgsql
POSTGRES_DB=dev
POSTGRES_USER=dev
POSTGRES_PASSWORD=test
PYTHONASYNCIODEBUG=1
PYTHONDONTWRITEBYTECODE=1
API_MODE=dev
API_ADMIN_EMAIL=admin@example.com
API_ADMIN_PASSWORD=password
API_WEBSOCKET_TIMEOUT=86400
It is a good idea to have different .env file for development, production and testing mode and of course, it shouldn't be inside the git repository for security reason.
I think the defined variables no need to be explained. Next step is creating the docker-compose.yml file:
version: '3.7'
networks:
web:
driver: bridge
internal:
driver: bridge
services:
redis:
container_name: test_redis
image: "redis:latest"
volumes:
- ${PWD}/.data/redis:/data
networks:
- internal
db:
restart: always
container_name: test_db
image: postgres:alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
networks:
- internal
volumes:
- ${PWD}/.data/postgresql:/var/lib/postgresql/data
- ${PWD}/db_entrypoint:/docker-entrypoint-initdb.d
adminer:
container_name: test_adminer
image: adminer
restart: always
env_file:
- .env
networks:
- internal
nginx:
container_name: test_nginx
image: "nginx:stable"
ports:
- "80:80"
volumes:
- ./nginx:/etc/nginx/conf.d
networks:
- web
- internal
env_file:
- .env
links:
- adminer
In 2–6 lines we defined 2 different networks: “web” and “internal”. The “web” will be used for exchange data between a client’s browser and web server (Nginx). The “internal” network will link “back-end services” between each other. More theory about networks can read here.
server {
listen 80;
server_name localhost;
location /db {
rewrite /db$ /db break;
rewrite /db/(.*) /db/$1 break;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_pass http://adminer:8080;
}
}
Read: "Part II. Dockerize SPA based on Nginx +VueJs+Python-Sanic. Python API."