乐趣区

关于docker: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/684490…

# 装置 Nginx
yum -y install nginx

# 卸载 Nginx
yum remove nginx

# 设置开机启动,倡议关上
systemctl enable nginx

# 启动 nginx 服务,装置后需运行
systemcrl start nginx

# 进行 nginx 服务
systemcrl stop nginx

# 重启 nginx 服务
systemcrl restart nginx

我的 Nginx 配置,以下仅为局部配置,可下载一键脚本进行配置。
如果不晓得本人的 Nginx 配置的文件地位在哪,可应用 systemctl status nginx 查看。

# 编辑的文件
# 我的文件地址是
# 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

# 装置 Docker
yum -y install docker

# 启动 Docker 后盾服务,装置完后需运行
systemctl start docker

# 开机自启动 Dokcer,倡议开启
systemctl enable docker

# 查看 Dokcer 运行信息
systemctl status docker

# 重启 Docker 服务
systemctl restart docker

# 检测 Docker 是否失常装置,尝试跑一个叫 hello-word 的镜像
docker run hello-world

# 查看是存在 hello-world 镜像,如果存在,则胜利
docker images

# 拉取 CentOS 镜像,留神 ':' 前面带的是零碎版本,# 同样的 docker images 能够查看是否存在 centos 这个镜像
docker pull centos:7.8.2003

# 运行 docker centos 的时候,# 肯定要留神凋谢端口,以不便容器内的 Fastapi 应用
docker run -ti -d -p 80:80 -p 8011:8011 --privileged=true centos:7.8.2003 /usr/sbin/init

# 查看所有镜像的信息,方便使用 container id 进入
docker ps -a

# 先执行 attach 命令,以取得 systemctl 权限
docker attach docker_container_id

# 下次进入 docker 就不是下面那句 attach 命令了,而是
docker exec -it docker_container_id /bin/bash
# 所以须要 docker ps -a 查看 container id

! 重要!:之后进入这个容器就不能用 docker attach docker_container_id 了,但为了保险,先 attach 一次,以取得容器内 CentOS 7 执行 systemctl 命令的权限

# 而后关掉终端或命令行,开启新的终端或命令行,这次换另外一条命令进入 虚拟机
docker exec -it docker_container_id /bin/bash

对于 CentOS 7 装置 Docker 更具体的信息:https://www.jianshu.com/p/3a4…

对于 Docker 装置 CentOS 7 及根本配置:https://victorzhong.github.io…


容器内虚拟机须要做的配置

1. 装置 & 配置PostgreSQL 12

记得在 sql shell 外面的命令,结尾都要加上 ; 分号。

# 先装置 yum 的下载源,即装置 epel-release,# 下载之后,就能够间接跳到 装置 PostgreSQl 12 那一步

#(还有其它的国内源请看:https://www.jianshu.com/p/541c737bc947)yum -y install epel-release

# 如果抉择不装置 yum 下载源 则应用上面的命令
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 装置 PostgreSQL 12
yum install -y postgresql12 postgresql12-server

# 初始化数据库
/usr/pgsql-12/bin/postgresql-12-setup initdb 

# 启动 PostgreSQL 服务
systemctl start postgresql-12

# 设置 PostgreSQL 服务为开机启动
systemctl enable postgresql-12

# 查看 PostgreSQL 服务状态
systemctl status postgresql-12

# 进入 PostgreSQL 命令行
su postgres

# 启动 SQL Shell
psql

! 重要!,此时先不要退出 sql shell!接下来,可输出 \l 查看 DataBaseEncoding,假若 Encoding 不为 UTF8,插入中文值到数据库的时候,会出错!

请先不要急着卸载或执行破坏性命令(血与泪的教训),请依照程序执行上面的命令,以更改 DataBaseEncoding

这些命令全都要在 SQL Shell 外面执行!记得 ; 分号结尾,如果还是忘了,按 ctrl / command + c 能够退回到初始状态。

# 先切换 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 这两个数据库

# 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 命令即可。

# 批改 postgres 数据库明码
ALTER USER postgres WITH PASSWORD 'NewPassword';

! 重要!,容许所有 IP 拜访,我的配置

# 批改配置文件
vi /var/lib/pgsql/12/data/pg_hba.conf

# 将 ipv4 上面的内容改为
# IPv4 local connections:
host    all             all               127.0.0.1/32          trust

# 重启 postgresql-12 服务,留神⚠️肯定要带上 -12
systemctl restart postgresql-12

# 如果须要退出 postgres=# 或 bash-4.2$ 的状态
间接输出 exit 按回车即可。

PostgreSQL 12 装置 & 配置结束

PostgreSQL 批改数据库编码方式代码源自🔗:https://www.jianshu.com/p/628…

更具体的信息可点击此链接🔗(大部分内容也源自此链接):https://ken.io/note/centos7-p…


2. 装置 & 配置 Anaconda

以下内容大部分来自此链接🔗:https://juejin.im/post/685457…

# 下载 wget
yum -y install wget

# 配置 下载源
yum -y install perl

# 下载 Anaconda
wget https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh

# 装置 Anaconda
bash Anaconda3-5.3.1-Linux-x86_64.sh

# 进入安装程序,提醒输出“ENTER”持续:Please, press ENTER  to continue
>>> ENTER

# 输出 yes 确认承受许可协定
Do you accept the license terms? [yes|no]
[no] >>> yes

# 确认 Anaconda 的装置地位, 可改可不改
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

# 装置实现后,呈现询问是否在用户的.bashrc 文件中初始化 Anaconda3 的相干内容,此处选 yes
Do you wish the installer to initialize Anaconda3by running conda init? [yes|no][no] >>> yes

装置实现 ✅,Anaconda 的一些根底命令:

# 执行下:source ~/.bashrc,# 应用 conda 命令时就不会报 conda command not found 了

# 创立一个 Python3.7 版本的虚拟环境
conda create --name fastapienv python=3.7

# 删除虚拟环境命令
conda remove -n fastapienv --all

# 激活虚拟环境,可间接激活虚拟环境,无需先停用以后虚拟环境
conda activate fastapienv

# 停用虚拟环境
conda deactivate fastapienv

# 查看以后虚拟环境已装置的包
conda list

# conda 安装包命令,如果是装置 fastapi
conda install fastapi

# 当 conda install 无奈装置某个包时,通过查问 pip 的门路,# 如果有显示以后虚拟环境名,则能够应用 pip 装置 Python 包,看是否能装上

whereis pip
pip install fastapi

# 如果 pip install / coonda install 都无奈装置,则须要下载源码包,应用命令解压装置。

解决每次进入虚拟机时,Anaconda 虚拟环境皆为 base 的问题
(源自此链接🔗:https://www.cnblogs.com/alpha…)

# 批改 ~/.bash_profile 文件,有时 ~/.bashrc 文件里也会有此配置

export PATH="~/anaconda/envs/your_env_name/bin:$PATH"
# your_env_name 是你自定义的环境名

# 批改 ~/.bashrc 文件

conda activate your_env_name
# "your_env_name" 就是你的环境名

# 更新配置
source ~/.bashrc
source ~/.bash_profile

# 设置好后,返回到刚进入虚拟机的状态 [root@xxx /]#,# 执行以下命令以进行 base 虚拟环境自启动
conda config --set auto_activate_base false

我的配置:

# vi ~/.bashrc

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__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_setup
conda activate fastapienv
# <<< conda initialize <<<

# vi ~/.bash_profile

# PATH=$PATH:$HOME/bin
PATH="~/anaconda3/envs/fastapienv/bin:$PATH"
export PATH
export LANG="en_US.UTF-8"

Anaconda 配置结束

我的 Anaconda 虚拟环境 fastapienv 还须要装置的包

# 除了根本的包以外

还装置了:fastapi
uvicorn
psycopg2

# 小程序解密用
pycryptodome

3. 装置 & 配置 & 启动一个 Fastapi 根底后端

fastapi 官网中文链接🔗:https://fastapi.tiangolo.com/zh/

执行上面的步骤前,必须先装置好 fastapi & uvicorn & psycopg2

# 找个你喜爱的门路,(我喜爱 /tmp/)创立 main.py 文件,键入以下代码:from typing import Optional
from fastapi import FastAPI

# 跨域
from fastapi.middleware.cors import CORSMiddleware

import psycopg2
import psycopg2.extras

app = 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=["*"]
)

# 个别都是 5432 端口,下文会提及如何查问
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 后,执行以下命令:

uvicorn main:app --host 0.0.0.0 --port 8011 --reload

# 按 ctrl / command + c 可进行运行

此时,你在浏览器的地址栏中输出,你的物理机 IP,前面加上:8011,就能看到 hello world 的提醒。

IP 后输出 :8011/docs 你还能看到 fastapi 为咱们筹备的 交互式 API 文档,你能够在外面测试连贯数据库是否存在问题。

:8011/docs 还能进行肯定的接口测试,看看返回的 Data 是否合乎本人的须要。

如键入中文值存在问题,请返回到上文,看看是否是,DataBase Encoding 的编码问题。

另外,如果你的 Uvicorn 在后盾运作,而你心愿重新启动,可应用以下命令让它进行运行

# 查看端口被哪个过程占用
netstat -lnp|grep 8011

# 如果无奈应用 netstat 执行:yum install net-tools

# 查看过程的详细信息
ps 11100

# 杀掉过程
kill -9 11100

# 通常,还需再应用 netstat -lnp|grep 8011 复查

更多详细信息:https://blog.csdn.net/u011389…


4. 可能存在的 Psycopg2 操作 PostgreSQL 数据库问题

如果没有 import psycopg2.extras & cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) 这段代码。

你的 /searchall/staff 申请的返回值,就不会以键值对的模式返回给前端。

以下内容你能够疏忽

当初我为了这个问题,“学习了”下 PostgreSQL json & jsonb 数据类型的操作,jsonb 的读取性能更快(比 json 快很多很多倍,然而程序会乱)

上面放一下 jsonb 的 数据库命令 操作,即,间接在 sql shell 中执行的命令

# 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

CREATE TABLE test_jsonb (
    id SERIAL PRIMARY KEY,
    info jsonb
);

id 为自增时,其它不变,插入数据变为:

insert into test_jsonb (info) values('{"company":"sanzro design","name":"sanzro","career":"Full Stack Engineer"}');

其它遇到的问题

后端解密小程序函数

! 重要!,须要 pip install pycryptodome,上文有提及

如果仍旧无奈应用,请参考此链接🔗:从“正告:请勿应用 pycrypto”看起:https://qastack.cn/programmin…

# 示例代码
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}

内容较长,感激 🙏 你看到这里。

如有误,请提出,必纠正,谢谢。

退出移动版