数据库安装配置

这节课我们将来配置MySQL数据库,启动运行在另外一个容器中,然后把它linkusers-service容器中......

增加Flask-SQLAlchemyPyMySQLrequirementx.txt文件中:

Flask-SQLAlchemy==2.3.2
PyMySQL==0.8.0

当然要记得安装这些依赖包:

(tdd3)$ pip install -r requirements.txt

然后更新config.py文件,添加SQLAlchemy数据库声明:

# project/config.py
import os

class BaseConfig:
    """基础配置"""
    DEBUG = False
    TESTING = False
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(BaseConfig):
    """开发环境配置"""
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')

class TestingConfig(BaseConfig):
    """测试环境配置"""
    DEBUG = True
    TESTING = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_TEST_URL')

class ProductionConfig(BaseConfig):
    """生产环境配置"""
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')

接下来更新__init__.py文件,创建一个SQLAlchemy实例然后定义数据模型:

# project/__init__.py
import os
import datetime
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy

# 初始化app
app = Flask(__name__)
# 环境配置
app_settings = os.getenv('APP_SETTINGS')
app.config.from_object(app_settings)

# 初始化数据库
db = SQLAlchemy(app)

class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(128), nullable=False)
    email = db.Column(db.String(128), nullable=False)
    active = db.Column(db.Boolean(), default=False, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)

    def __init__(self, username, email):
        self.username = username
        self.email = email
        self.created_at = datetime.datetime.utcnow()

@app.route('/ping', methods=['GET'])
def ping_pong():
    return jsonify({
        'status': 'success',
        'message': 'pong!'
    })

project目录下增加一个db的文件夹,在下面新建一个create.sql的文件:

CREATE DATABASE users_prod;
CREATE DATABASE users_dev;
CREATE DATABASE users_test;

然后在db目录下面添加文件Dockerfile:

FROM mysql:5.6

# 初始化的时候运行create.sql脚本
ADD create.sql /docker-entrypoint-initdb.d

这里我们继承官方的mysql镜像,在docker-entrypoint-initdb.d目录下面增加一个SQL文件,容器在初始化的时候就会执行这个sql文件。

更新docker-compose.yml

version: '2.1'

services:
  users-db:
    container_name: users-db
    build: ./project/db
    ports:
      - 3307:3306
    environment:
      - MYSQL_ROOT_PASSWORD=root321
    healthcheck:
      test: exit 0

  users-service:
    container_name: users-service
    build: ./
    volumes:
      - '.:/usr/src/app'
    ports:
      - 5001:5000 # 暴露端口 - 主机:容器
    environment:
      - APP_SETTINGS=project.config.DevelopmentConfig
      - DATABASE_URL=mysql+pymysql://root:root321@users-db:3306/users_dev
      - DATABASE_TEST_URL=mysql+pymysql://root:root321@users-db:3306/users_test
    depends_on:
      users-db:
        condition: service_healthy
    links:
      - users-db

启动后注入环境变量exit code被发送后容器成功运行起来,MySQL将被绑定在宿主机的3307和容器的3306端口上。注意DATABASE_URL路径中使用的mysql+pymysql,因为我们使用的是python3.6.x版本和pymysql驱动。 检测:

(tdd3)$ docker-compose up -d --build

然后更新manage.py,增加创建数据库的命令:

from flask_script import Manager
from project import app, db

manager = Manager(app)

@manager.command
def recreate_db():
    """重新创建数据表."""
    db.drop_all()
    db.create_all()
    db.session.commit()

if __name__ == '__main__':
    manager.run()

新添加了一个recrete_db的命令,我们可以在命令行中执行该命令来将model映射到数据中:

(tdd3)$ docker-compose run users-service python manage.py recreate_db

如果一切正常的话,上面的命令能够执行成功,然后我们来验证下数据库中是否有对应的数据表了:

(tdd3)$ docker exec -it users-db mysql -uroot -p
Enter password:

然后输入上面我们环境变量中设置的root321就登录到MySQL数据库中了。然后执行下面的系列命令查看数据库、查看数据表结构:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| users_dev          |
| users_prod         |
| users_test         |
+--------------------+
6 rows in set (0.00 sec)

mysql> use users_dev;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+---------------------+
| Tables_in_users_dev |
+---------------------+
| users               |
+---------------------+
1 row in set (0.00 sec)

mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| username   | varchar(128) | NO   |     | NULL    |                |
| email      | varchar(128) | NO   |     | NULL    |                |
| active     | tinyint(1)   | NO   |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

从上面的命令我们可以看到model和我们的数据表已经映射成功了。