Background

這篇主要紀錄一下如何 把之前的專案 flask-vue-crud 加入 Postgres 的服務。那開始之前先描述我自己的開發環境&正式環境,開發環境是在 Mac 上,正式環境則是 AWS 的 EC2,所以對我來說這兩個環境是很不一樣的,差別在於 Mac 本機上的 Postgres 我之後想用 Docker images 取代,這樣可以建立一鍵安裝的流程,但是在 AWS 上,由於我使用了 RDS 的服務所以不能用 Docker images 取代,因此之後的 docker-comspose.yml 會分成 dev & 正常的版本。

PostgreSQL Config

這個 section 主要會介紹兩種 docker-comspose.yml 的差異以及對應到 Flask config 的情況。

docker-compose.yml

version: '3'
services:
  nginx:
    image: ${DOCKER_REGISTRY}/nginx:${BRANCH}
    restart: always
    build:
      dockerfile: Dockerfile
      context: ./nginx
    ports:
      - '3000:3000'
      - '5000:5000'
  api:
    image: ${DOCKER_REGISTRY}/server:${BRANCH}
    build:
      dockerfile: Dockerfile
      context: ./server
      args:
        ENV: ${BRANCH}
  client:
    image: ${DOCKER_REGISTRY}/client:${BRANCH}
    build:
      dockerfile: Dockerfile
      context: ./client
      args:
        ENV: ${BRANCH}

docker-compose.dev.yml

version: '3'
services:
  postgres:
    image: postgres:11.5
    restart: always
    ports:
        - '5432:5432'
    environment:
        POSTGRES_USER: taiker
        POSTGRES_DB: flask-vue

  nginx:
    image: ${DOCKER_REGISTRY}/nginx:${BRANCH}
    restart: always
    build:
      dockerfile: Dockerfile
      context: ./nginx
    ports:
      - '3000:3000'
      - '5000:5000'

  api:
    image: ${DOCKER_REGISTRY}/server:${BRANCH}
    environment:
      - PGUSER=taiker
      - PGDATABASE=flask-vue
      - PGHOST=postgres
      - PGPORT=5432
    build:
      dockerfile: Dockerfile
      context: ./server
      args:
        ENV: ${BRANCH}
    depends_on:
      - postgres
    volumes:
      - ./server:/app

  client:
    image: ${DOCKER_REGISTRY}/client:${BRANCH}
    build:
      dockerfile: Dockerfile
      context: ./client
      args:
        ENV: ${BRANCH}

server/config.py

import os

class Config(object):
    # flask default setting
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    SQLALCHEMY_POOL_SIZE = 20
    SQLALCHEMY_POOL_TIMEOUT = 10
    SQLALCHEMY_POOL_RECYCLE = 1200
    SCHEDULER_API_ENABLED = True


class ProductionConfig(Config):
    DEBUG = False
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "prd"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:@{$RDS_HOST}/flask-vue"

class DevelopmentConfig(Config):
    DEVELOPMENT = True
    DEBUG = True
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "dev"
    SQLALCHEMY_DATABASE_URI = "postgresql://{}:@{}/{}".format(os.getenv("PGUSER"), os.getenv("PGHOST"), os.getenv("PGDATABASE"))

class TestingConfig(Config):
    TESTING = True
    DEBUG = True
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "qa"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:@{$RDS_HOST}/flask-vue"

class StagingConfig(Config):
    DEBUG = False
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "stg"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:@{$RDS_HOST}/flask-vue"


config = {
    "dev": DevelopmentConfig,
    "qa": TestingConfig,
    "stg": StagingConfig,
    "prd": ProductionConfig,
    "default": DevelopmentConfig,
}

首先我們先比較 docker-compose.dev.ymldocker-compose.yml。這兩個檔案主要的差別在於 postgres service。原因我們在 Background 中有提到,我們希望在我們的 Mac 能夠一鍵完成所有要安裝的檔案和啟動服務,但是在 AWS 上是直接跟 RDS 做連接的所以就不需要 postgres image。再來 dev 主要是 for 開發使用,所以在 api service 的部分多了 volumes 的部分用來加速開發。

我們可以對應到 Flask 的 config 檔,基本上連接到 Postgres 設定上也是蠻單純的。以 DevelopmentConfig 為例把在 docker-compose.dev.yml 中設定的 environment variablees 取出填入即可。

Start on Mac

介紹完了程式碼的部分後,我們來在local端執行看看。

Setting

$ git clone https://github.com/TaikerLiang/flask-vue-crud.git
$ cd flask-vue-crud
$ git checkout db
$ vim .env

.env

DOCKER_REGISTRY=YOUR_DOCKER_REGISTRY
BRANCH=dev
  • DOCKER_REGISTRY: 自己填入你常用的 DOCKER_REGISTRY 位置
  • BRANCH: 因為我們在 local 端 run 所以填入 dev

Start docker-compose

$ docker-compose -f docker-compose.dev.yml up --build -d
....
....
....
Creating flask-vue-crud_nginx_1    ... done
Creating flask-vue-crud_client_1   ... done
Creating flask-vue-crud_postgres_1 ... done
Creating flask-vue-crud_api_1      ... done
# initial db
$ docker-compose exec -e FLASK_APP=run.py api flask initdb
# initial data
$ docker-compose exec -e FLASK_APP=run.py api flask test

都沒問題之後我們打開瀏覽器輸入 http://localhost:3000/ 即可看到以下畫面:

Screen-Shot-2019-08-22-at-5.38.07-PM

測試完記得 stop container

$ docker-compose stop

Start on EC2 (Ubuntu)

Setting

$ git clone https://github.com/TaikerLiang/flask-vue-crud.git
$ cd flask-vue-crud
$ git checkout db
$ vim .env

.env

DOCKER_REGISTRY=YOUR_DOCKER_REGISTRY
BRANCH=qa
  • DOCKER_REGISTRY: 自己填入你常用的 DOCKER_REGISTRY 位置
  • BRANCH: 因為我們在 ec2 上所以填入 qa

Config

client/src/config.js

let config;

console.log(process.env);

if (process.env.VUE_APP_ENV === "dev") {
  config = {
    $api_url: "http://localhost",
    timeoutDuration: 30000,
  };
} else {
  config = {
    $api_url: "http://52.192.239.166",
    timeoutDuration: 1000,
  };
}

export { config }

http://52.192.239.166 換成你 EC2 的 ip。

server/config.py

import os

class Config(object):
    # flask default setting
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    SQLALCHEMY_POOL_SIZE = 20
    SQLALCHEMY_POOL_TIMEOUT = 10
    SQLALCHEMY_POOL_RECYCLE = 1200
    SCHEDULER_API_ENABLED = True
    
class ProductionConfig(Config):
    DEBUG = False
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "prd"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:{$PASSWORD}@{$RDS_HOST}/flask-vue"

class DevelopmentConfig(Config):
    DEVELOPMENT = True
    DEBUG = True
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "dev"
    SQLALCHEMY_DATABASE_URI = "postgresql://{}:@{}/{}".format(os.getenv("PGUSER"), os.getenv("PGHOST"), os.getenv("PGDATABASE"))

class TestingConfig(Config):
    TESTING = True
    DEBUG = True
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "qa"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:{$password}@dev.xxxxxxxx.ap-northeast-1.rds.amazonaws.com/flask-vue"

class StagingConfig(Config):
    DEBUG = False
    DOMAIN = "http://127.0.0.1:5000"
    BRANCH = "stg"
    SQLALCHEMY_DATABASE_URI = "postgresql://taiker:{$PASSWORD}@{$RDS_HOST}/flask-vue"

config = {
    "dev": DevelopmentConfig,
    "qa": TestingConfig,
    "stg": StagingConfig,
    "prd": ProductionConfig,
    "default": DevelopmentConfig,
}

把 TestingConfig 中的 SQLALCHEMY_DATABASE_URI 填入你 AWS RDS Instance 的相關資訊。

Start docker-compose

$ docker-compose up --build -d
....
....
....
Creating flask-vue-crud_nginx_1    ... done
Creating flask-vue-crud_client_1   ... done
Creating flask-vue-crud_api_1      ... done
# initial db
$ docker-compose exec -e FLASK_APP=run.py api flask initdb
# initial data
$ docker-compose exec -e FLASK_APP=run.py api flask test

接下來就打開 http://52.192.239.166:3000 即可看到一樣的畫面。(記得 EC2 的 3000 & 5000 port 要打開)

Reference