本篇介绍使用Fastapi + sqlalchemy + alembic 来完成后端服务的数据库管理,并且通过docker-compose来部署后端服务和数据库Mysql。包括:

  1. 数据库创建,数据库用户创建
  2. 数据库服务发现
  3. Fastapi 连接数据库
  4. Alembic 连接数据库
  5. 服务健康检查

部署数据库

version: '3'
services:
db:
image: mysql
container_name: db
environment:
- MYSQL_ROOT_PASSWORD=tv_2024 # root用户密码
- MYSQL_DATABASE=tileView
- MYSQL_USER=tile_viewer
- MYSQL_PASSWORD=tv_2024
- TZ=Asia/Shanghai
volumes:
- ./mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
ports:
- 3306:3306
restart: always

部署数据库有三个注意点:

  1. 将数据库文件映射出来,避免丢失数据

数据库中存储的数据都容器里在/var/lib/mysql目录下,将该目录映射出来,避免重启容器丢失数据

二、自动创建数据库DB

很多情况下需要在启动数据库容器是自动创建数据库,在environment中设置 MYSQL_DATABASE=tileView即可在容器启动是创建数据库

三、创建可读写可远程用户

默认情况下非root用户不支持远程连接读写权限,在environment中设置

  1. MYSQL_USER=tile_viewer
  2. MYSQL_PASSWORD=tv_2024

将会获得一个可远程可读写MYSQL_DATABASE库的用户

Fastapi 连接数据库

非docker部署情况下使用IP和端口连接数据库,使用docker-compose部署时服务都是自动化启动,事先不知道数据库的IP,这是就可以使用docker-compose提供的能力:使用服务名来请求服务。

docker-compose中可以使用服务的名称来通信,在通信请求中将服务名替换成容器IP。

首先将数据库连接的URL映射到服务的容器中

version: '3'
services:
db:
image: mysql
container_name: db
environment:
- MYSQL_ROOT_PASSWORD=tv_2024 # root用户密码
- MYSQL_DATABASE=tileView
- MYSQL_USER=tile_viewer
- MYSQL_PASSWORD=tv_2024
- TZ=Asia/Shanghai
volumes:
- ./mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
ports:
- 3306:3306
restart: always
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 10s
timeout: 5s
retries: 3
server:
image: tileview:1.0
restart: always
container_name: tileview_server
ports:
- "9100:9100"
volumes:
- ./tiles_store:/app/server/tiles_store
- ./log:/app/server/log
- ./upload:/app/server/upload
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URI=mysql+pymysql://tile_viewer:tv_2024@db/tileView

depends_on: 表示该服务依赖db服务,db服务要先启动。condition: service_healthy

DATABASE_URI:表示将数据库连接信息注入到该容器中,其中@db表示数据库IP:端口号 使用数据库服务名称db来替换,在容器中请求该url时,docker-compose会自动将db转换成对应的数据库的IP和端口号。

depends_on:
- db
environment:
- DATABASE_URI=mysql+pymysql://tile_viewer:tv_2024@db/tileView

修改sqlalchemy中数据库的连接

sqlalchemy 连接数据库时,数据库的url配置从环境变量中获取

sqlalchemy/database.py

import os

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URI")
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base()

使用环境变量获取数据库

SQLALCHEMY_DATABASE_URL = os.getenv("DATABASE_URI")

在Fastapi 服务 调用数据库的方法。

DATABASE_URI=mysql+pymysql://tile_viewer:tv_2024@db/tileView

使用数据库服务名db来找到服务地址,在docker-compose中会将服务名解析成服务的IP。在使用时会将db解析成172.10.0.2,找到服务的IP。

迁移工具alembic中数据库连接

在数据库迁移工具中需要配置数据库的连接信息,该信息是配置在alembic.ini中,如果要使用环境变量中动态获取的方法,需要改变两点:

  1. alembic.ini中不配置数据库连接信息
  2. 在alembic/env.py动态获取连接url,并设置到alembic.ini中

alembic.ini中不配置数据库连接信息

在alembic/env.py动态获取连接url,并设置到alembic.ini中

alembic/env.py

from logging.config import fileConfig

from alembic import context
from sqlalchemy import engine_from_config, pool # this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config # Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name) # add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = None # other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc. import os # noqa
import sys # noqa from server.db.base import Base # noqa basedir = os.path.split(os.getcwd())[0]
sys.path.append(basedir) target_metadata = Base.metadata def get_url() -> str:
return os.getenv("DATABASE_URI", "sqlite:///app.db") def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode. This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available. Calls to context.execute() here emit the given string to the
script output. """
# url = config.get_main_option("sqlalchemy.url")
url = get_url()
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
) with context.begin_transaction():
context.run_migrations() def run_migrations_online() -> None:
"""Run migrations in 'online' mode. In this scenario we need to create an Engine
and associate a connection with the context. """
configuration = config.get_section(config.config_ini_section)
configuration["sqlalchemy.url"] = get_url()
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
) with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction():
context.run_migrations() if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

在 run_migrations_offline 中将url获取从配置文件中改成从环境变量中

# url = config.get_main_option("sqlalchemy.url")
url = get_url()

在 run_migrations_online 中修改配置文件的数据库连接信息

configuration = config.get_section(config.config_ini_section)
configuration["sqlalchemy.url"] = get_url()
connectable = engine_from_config(
configuration,
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)

以上操作之后就能通过服务发现的方式动态使用数据库

数据库健康检查

在前面的配置中虽然让服务依赖db,db会先启动然后服务后启动,但是这种情况还会出现数据库连不上的情况,因为db启动不代表服务就绪,未就绪的时候连接会导致connect refuse。解决这个问题的方法是给db增加一个健康检查 healthcheck。

services:
db:
image: mysql
container_name: db
environment:
- MYSQL_ROOT_PASSWORD=tv_2024 # root用户密码
- MYSQL_DATABASE=tileView
- MYSQL_USER=tile_viewer
- MYSQL_PASSWORD=tv_2024
- TZ=Asia/Shanghai
volumes:
- ./mysql:/var/lib/mysql
- /etc/localtime:/etc/localtime:ro
ports:
- 3306:3306
restart: always
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 10s
timeout: 5s
retries: 3

当健康检查完成才代表数据库启动成功,服务才会启动。服务中也需要依赖数据库健康检查完成,写法如下:

depends_on:
db:
condition: service_healthy

docker-compose部署下Fastapi中使用sqlalchemy和Alembic的更多相关文章

  1. 使用Docker Compose 部署Nexus后初次登录账号密码不正确,并且在nexus-data下没有admin,password

    场景 Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/ ...

  2. Docker Compose 部署前后端分离应用

    部署前后端分离应用 容器化 Abp 应用 关于 Abp 应用的容器化,其实和普通的 ASP.NET Core 应用差不多,大家可以参考我此前的文章. 唯一需要注意的是:因为 Abp 解决方案中有多个项 ...

  3. 在Windows Server 2019通过Docker Compose部署Asp.Net Core

    一.安装Docker Enterprise 安装文档是: https://docs.docker.com/install/windows/docker-ee/ 安装完成后,如下图 二.首先,拉取一个W ...

  4. Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程)

    场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  5. Docker Compose 部署 Redis 及原理讲解 | 懒人屋

    原文:Docker Compose 部署 Redis 及原理讲解 | 懒人屋 Docker Compose 部署 Redis 及原理讲解  4.4k  字    16  分钟    2019-10-1 ...

  6. 基于Docker Compose部署分布式MinIO集群

    一.概述 Minio 是一个基于Go语言的对象存储服务.它实现了大部分亚马逊S3云存储服务接口,可以看做是是S3的开源版本,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器 ...

  7. Docker Compose部署GitLab服务,搭建自己的代码托管平台(图文教程)

    场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  8. 使用Docker Compose 部署Nexus后提示:Unable to create directory /nexus-data/instance

    场景 Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/ ...

  9. Docker Compose部署 EFK(Elasticsearch + Fluentd + Kibana)收集日志

    简述 本文用于记录如何使用Docker Compose部署 EFK(Elasticsearch + Fluentd + Kibana) 收集Docker容器日志,使用EFK,可以无侵入代码,获得灵活, ...

  10. 使用Docker Compose部署基于Sentinel的高可用Redis集群

    使用Docker Compose部署基于Sentinel的高可用Redis集群 https://yq.aliyun.com/articles/57953 Docker系列之(五):使用Docker C ...

随机推荐

  1. 今日一学,sql优化,创建索引的优缺点

    收藏了,但是不打开,久而久之就忘了,今日一学!所谓是好记性不如烂键盘. ** 2024Java offer收割指南 ** sql优化 尽量避免使用 select * ,返回无用的字段会降低效率.优化方 ...

  2. 面试:靠着这篇笔记,我拿下了16k车载测试offer!

    如何写简历个人技能个人技能一般不要超过10条,一般在8条内. 一.测试流程和技术 1.熟悉车载系统研发和测试流程,能独立编写各种测试文档. 2.熟悉车载系统测试用例设计思路,能独立编写仪表和车机的测试 ...

  3. Spark原理及关键技术点

    Spark Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎.Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop M ...

  4. 强化学习:gym下atari游戏环境的官方文档地址

    2024年10月16日 共建议查看两个历史上的官方地址: https://ale.farama.org/ https://www.gymlibrary.dev/ 最新官方地址: https://ale ...

  5. UE4纯C++实现游戏快捷栏之创建快捷栏UI

    作为一个在游戏界面中显示的快捷栏,我们需要在游戏运行时就显示出快捷栏UI,故我们创建两个Widget. 1.GameHUDWidget:负责游戏中界面UI的整体显示 2.ShortcutWidget: ...

  6. Python爬虫之数据解析

    1.Request库 HTTP测试工具:http://httpbin.org,以下的示例会以此为URL 属于第三方库,需要手动安装 pip install requests 基本用法 import r ...

  7. VMware使用及CentOS 7安装配置

    本文是在VMware虚拟机下安装CentOS 7的,并不是在物理机下直接安装.无论是在学习上还是工作上都建议在虚拟机安装Linux系统来进行实验.这样就算实验失败,或者系统崩溃.只需要使用虚拟机的快照 ...

  8. vue+laravel使用微信Natvite支付

    Navite支付介绍 Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信"扫一扫"完成支付的模式.适用于PC网站.实体店单品或订单.媒体广告支付等场景 1.先阅 ...

  9. 读书笔记-C#8.0本质论-05

    18.3 基于任务的异步编程模式 18.3.1 使用任务并行库(TPL)实现异步执行高延迟操作 using System; using System.Net.Http; using System.Th ...

  10. SpringMVC-Mybatis-Maven项目整合

    上次不知道为什么,把写好的系列文章都搞成一样了.结果,五篇文章,都变成了最后一篇文章. 悲剧,好吧,只好重新写了. 这系列文章写的是SpringMVC-Mybatis-Maven项目整合.说白了,其实 ...