Dokcer + CentOS 7 + Anaconda + FastAPI + PostgreSQL 超详细配置 & 出错解决
首先讲讲我的配置清单🧾 宿主机 OS: CentOS 7
Nginx 版本:1.16.1
Docker 版本: 19.03.13
Docker 容器系统: CentOS 7
Python 虚拟环境管理: Anaconda
Python 版本: Python 3.7
选用的后端框架: Fastapi
Python 操作 PostgreSQL: Psycopg2
(毋容置疑) 数据库: PostgreSQL 12
(毋容置疑 + 1)
宿主机中需要做的配置 1. 安装 & 配置 Nginx
大部分内容出自此链接 🔗:https://juejin.im/post/6844904134345228301
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 yum -y install nginx yum remove nginx systemctl enable nginx systemcrl start nginx systemcrl stop nginx systemcrl restart nginx
我的 Nginx 配置,以下仅为部分配置,可下载一键脚本进行配置。 如果不知道自己的 Nginx 配置的文件位置在哪,可使用 systemctl status nginx
查看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 编辑的文件 # 我的文件地址是 # vi /etc/nginx/conf.d/default.conf server { listen 80; server_name www.xxx.xxx; rewrite ^(.*)$ https://$host$1 permanent; } server { listen 443 ssl http2; server_name www.xxx.xxx; root /etc/nginx/html; index index.php index.html; location / { try_files $uri $uri/ /index.php?$args; } # fastapi main location /helloworld { proxy_pass http://127.0.0.1:8011; } # fastapi docs location /docs { proxy_pass http://127.0.0.1:8011/api/docs; } }
2. 安装 & 配置 Docker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 yum -y install docker systemctl start docker systemctl enable docker systemctl status docker systemctl restart docker docker run hello-world docker images docker pull centos:7.2.1511 docker run -ti -d -p 80:80 -p 8011:8011 --privileged=true centos:7.8.2003 /usr/sbin/init docker ps -a docker attach docker_container_id docker exec -it docker_container_id /bin/bash
!重要!:之后进入这个容器就不能用 docker attach docker_container_id
了,但为了保险,先 attach
一次,以获得容器内 CentOS 7
执行 systemctl
命令的权限
1 2 docker exec -it docker_container_id /bin/bash
关于 CentOS 7 安装 Docker 更详细的信息:https://www.jianshu.com/p/3a4cd73e3272
关于 Docker 安装 CentOS 7 及基本配置:https://victorzhong.github.io/2018/01/15/Docker%E5%AE%89%E8%A3%85CentOS7%E5%8F%8A%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE/
容器内虚拟机需要做的配置 1. 安装 & 配置PostgreSQL 12
记得在 sql shell
里面的命令,结尾都要加上 ;
分号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 yum -y install epel-release yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm yum install -y postgresql12 postgresql12-server /usr/pgsql-12/bin/postgresql-12-setup initdb systemctl start postgresql-12 systemctl enable postgresql-12 systemctl status postgresql-12 su postgres psql
!重要!,此时先不要退出 sql shell
!接下来,可输入 \l
查看 DataBase
的 Encoding
,假若 Encoding
不为 UTF8
,插入中文值到数据库的时候,会出错!
请先不要急着卸载或执行破坏性命令(血与泪的教训),请按照顺序执行下面的命令,以更改 DataBase
的 Encoding
。
这些命令全都要在 SQL Shell
里面执行!记得 ;
分号结尾,如果还是忘了,按 ctrl / command + c 可以退回到初始状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 # 先切换 DataBase \c template0; # 将 template1 的 datistemplate 改为 false update pg_database set datistemplate = FALSE where datname = 'template1' ; # 删除 template1 DataBase drop database template1;# 重新创建 template1 DataBase 以 UTF8 编码 create database template1 with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template0;# 重新将 template1 的 datistemplate 改为 true update pg_database set datallowconn = TRUE where datname = 'template1' ; # 接下来切换到 template1 Database \c template1; # 重复步骤,修改 template0 的 datistemplate update pg_database set datistemplate = FALSE where datname = 'template0' ; # 删除 template0 DataBase drop database template0;# 重新创建 template0 DataBase 以 UTF8 编码 create database template0 with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template1;# 重新将 template0 的 datistemplate 改为 true update pg_database set datallowconn = TRUE where datname = 'template0' ;
!重要!,切勿真的删除 template0
& template1
这两个数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # postgres 数据库,重复以上步骤,即可把 Encoding 改为 UTF8,不再赘述注释 \c template1; update pg_database set datistemplate = FALSE where datname = 'postgres' ; drop database template0;create database postgres with encoding = 'UTF8' LC_CTYPE = 'en_US.UTF-8' LC_COLLATE = 'en_US.UTF-8' template = template0;update pg_database set datallowconn = TRUE where datname = 'postgres' ; \c postgres; # 再次输入 \l 查看 Encoding,确保修改成功。
当执行了破坏性命令,例如:yum remove postgresql12 postgresql12-server
。
并重新执行了yum install postgresql12 postgresql12-server
后,执行初始化数据库命令时会出错,
即当在[root@xxx /]#
状态下执行 /usr/pgsql-12/bin/postgresql-12-setup initdb
命令时会出现,该文件夹 📁 不为空的报错 。
此时需执行:rm -rf /var/lib/pgsql/12/data/
删除该文件夹。
然后重新执行 /usr/pgsql-12/bin/postgresql-12-setup initdb
命令即可。
1 2 # 修改 postgres 数据库密码 ALTER USER postgres WITH PASSWORD 'NewPassword' ;
!重要!,允许所有 IP 访问,我的配置
1 2 3 4 5 6 7 8 9 10 11 12 vi /var/lib/pgsql/12/data/pg_hba.conf host all all 127.0.0.1/32 trust systemctl restart postgresql-12 直接输入 exit 按回车即可。
PostgreSQL 12
安装 & 配置完毕
PostgreSQL
修改数据库编码方式代码源自🔗:https://www.jianshu.com/p/62893363b0d2
更详细的信息可点击此链接🔗(大部分内容也源自此链接):https://ken.io/note/centos7-postgresql12-install-and-configuration
2. 安装 & 配置 Anaconda
以下内容大部分来自此链接🔗:https://juejin.im/post/6854573222273220621
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 yum -y install wget yum -y install perl wget https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh bash Anaconda3-5.3.1-Linux-x86_64.sh Please, press ENTER to continue >>> ENTER Do you accept the license terms? [yes|no] [no] >>> yes Anaconda3 will now be installed into this location:/root/anaconda3 - Press ENTER to confirm the location - Press CTRL-C to abort the installation - Or specify a different location below[/root/anaconda3] >>> /opt/anaconda3 Do you wish the installer to initialize Anaconda3by running conda init? [yes|no][no] >>> yes
安装完成 ✅ ,Anaconda
的一些基础命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 conda create --name fastapienv python=3.7 conda remove -n fastapienv --all conda activate fastapienv conda deactivate fastapienv conda list conda install fastapi whereis pip pip install fastapi
解决每次进入虚拟机时,Anaconda
虚拟环境皆为 base
的问题 (源自此链接🔗:https://www.cnblogs.com/alphacode/p/13760470.html)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 export PATH="~/anaconda/envs/your_env_name/bin:$PATH " conda activate your_env_name source ~/.bashrcsource ~/.bash_profileconda config --set auto_activate_base false
我的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 __conda_setup="$('/root/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null) " if [ $? -eq 0 ]; then eval "$__conda_setup " else if [ -f "/root/anaconda3/etc/profile.d/conda.sh" ]; then . "/root/anaconda3/etc/profile.d/conda.sh" else export PATH="/root/anaconda3/bin:$PATH " fi fi unset __conda_setupconda activate fastapienv PATH="~/anaconda3/envs/fastapienv/bin:$PATH " export PATHexport LANG="en_US.UTF-8"
Anaconda
配置完毕
我的 Anaconda
虚拟环境 fastapienv
还需要安装的包
1 2 3 4 5 6 7 8 9 # 除了基本的包以外 还安装了: fastapi uvicorn psycopg2 # 小程序解密用 pycryptodome
3. 安装 & 配置 & 启动一个 Fastapi
基础后端 fastapi官方中文链接🔗:https://fastapi.tiangolo.com/zh/
执行下面的步骤前,必须先安装好 fastapi & uvicorn & psycopg2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 from typing import Optional from fastapi import FastAPIfrom fastapi.middleware.cors import CORSMiddlewareimport psycopg2import psycopg2.extrasapp = FastAPI() origins = [ "http://localhost.tiangolo.com" , "https://localhost.tiangolo.com" , "http://localhost" , "http://localhost:8080" , "http://127.0.0.1" , "http://127.0.0.1:8080" , "*" ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True , allow_methods=["*" ], allow_headers=["*" ] ) conn = psycopg2.connect(database="postgres" , user="postgres" , password="Your_Pass_Word" , host="127.0.0.1" , port="5432" ) cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) @app.get("/" ) def read_root (): return {"Hello" : "World" } @app.get("/create/stafftable" ) def create_staff_table (): sql = """ CREATE TABLE staff( id varchar(11) PRIMARY KEY, username varchar(20), password varchar(50) ); """ try : cursor.execute(sql) print ("staff table created successfully" ) conn.commit() except Exception as e: conn.rollback() else : conn.commit() @app.get("/create/staff" ) def create_staff (id : str , username: str , password: str ): idsql = """SELECT * FROM staff where id = %s""" idparams = (id ,) cursor.execute(idsql, idparams) conn.commit() rows = cursor.fetchall() if rows: return -1 else : sql = """INSERT INTO staff (id, username, password) VALUES (%(id)s,%(username)s, %(password)s)""" params = {'id' : id , 'username' : username, 'password' : password} try : cursor.execute(sql, params) conn.commit() except Exception as e: conn.rollback() else : conn.commit() @app.get("/delete/staff" ) def delete_staff (id : str ): sql = """delete from staff where id = %s """ params = (id ,) try : cursor.execute(sql, params) conn.commit() except Exception as e: conn.rollback() else : conn.commit() @app.get("/searchall/staff" ) def search_all_staff (): sql = """SELECT * FROM staff;""" try : cursor.execute(sql) rows = cursor.fetchall() conn.commit() return rows except Exception as e: conn.rollback() else : conn.commit() def close_database (): cursor = conn.cursor() cursor.close() conn.close()
!重要!,此时,我们进来 Dokcer
容器的那条命令就发挥作用了,我们进入的时候,映射了两个端口给虚拟机,分别是 80
& 8011
。
如果你没有跑 docker run -ti -d -p 80:80 -p 8011:8011 --privileged=true centos:7.8.2003 /usr/sbin/init
这条命令就进入虚拟机,很抱歉,你需要回到创建 docker container 的位置重新创建…
写好 main.py
后,执行以下命令:
1 2 3 uvicorn main:app --host 0.0.0.0 --port 8011 --reload
此时,你在浏览器的地址栏中输入,你的物理机IP,后面加上:8011
,就能看到 hello world
的提示。
IP后输入 :8011/docs
你还能看到 fastapi
为我们准备的 交互式 API 文档,你可以在里面测试连接数据库是否存在问题。
:8011/docs
还能进行一定的接口测试,看看返回的 Data 是否符合自己的需要。
如键入中文值存在问题,请返回到上文,看看是否是,DataBase Encoding
的编码问题。
另外,如果你的 Uvicorn
在后台运作,而你希望重新启动,可使用以下命令让它停止运行
1 2 3 4 5 6 7 8 9 10 11 12 13 netstat -lnp|grep 8011 yum install net-tools ps 11100 kill -9 11100
更多详细信息:https://blog.csdn.net/u011389452/article/details/53982204
4. 可能存在的 Psycopg2
操作 PostgreSQL
数据库问题 如果没有 import psycopg2.extras
& cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
这段代码。
你的 /searchall/staff
请求的返回值,就不会以键值对的形式返回给前端。
以下内容你可以忽略
当初我为了这个问题,“学习了”下 PostgreSQL
json
& jsonb
数据类型的操作,jsonb
的读取性能更快(比 json
快很多很多倍,但是顺序会乱)
下面放一下 jsonb
的 数据库命令 操作,即,直接在 sql shell
中执行的命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # postgresql jsonb 增删改查 知识点记录 📝 (注意!是jsonb): # 在 sql shell 创建表: CREATE table test_jsonb(id int , info jsonb);# 增: insert into test_jsonb values (2 , '{"company":"sanzro design", "name":"sanzro", "career":"Full Stack Engineer"}' );# 删(暂时不知道如何通过jsonb去删除整个元素): delete from test_jsonb where id = 2 ;# 改: update test_jsonb set info = info|| '{"company":"sanzro design"}' WHERE id = 2 ; # 查: select * from test_jsonb where info @> '{"company":"sanzro design"}' ;# 查询 id select * from test_jsonb where id= 2 ;
还有如果你需要 id
自增,则创建表的时候将 id
配置为 serial
:
1 2 3 4 CREATE TABLE test_jsonb ( id SERIAL PRIMARY KEY, info jsonb );
当 id
为自增时,其它不变,插入数据变为:
1 insert into test_jsonb (info) values ('{"company":"sanzro design", "name":"sanzro", "career":"Full Stack Engineer"}' );
其它遇到的问题 后端解密小程序函数
!重要!,需要 pip install pycryptodome
,上文有提及 如果依旧无法使用,请参考此链接🔗:从 “警告:请勿使用 pycrypto
” 看起:https://qastack.cn/programming/19623267/importerror-no-module-named-crypto-cipher
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from fastapi.encoders import jsonable_encoder@app.post('/code' ) def user_wxlogin (appid, secret, code ): params = { 'appid' : appid, 'secret' : secret, 'js_code' : code, 'grant_type' : 'authorization_code' } url = 'https://api.weixin.qq.com/sns/jscode2session' r = requests.get(url, params=params) openid = r.json().get('openid' , '' ) session_key = r.json().get('session_key' , '' ) return {'openid' : openid, 'session_key' : session_key}
内容较长,感谢 🙏 你看到这里。
如有误,请提出,必纠正,谢谢。