docker部署chat-web,实现自己的ChatGPT

Posted wd520521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker部署chat-web,实现自己的ChatGPT相关的知识,希望对你有一定的参考价值。

本篇文章的前提是请确认已获得openai 的API-KEYS,即以sk-开头的keys;是否在服务器上安装了docker以及docker-compose

docker以及docker-compose安装请参考我的博文:CENTOS8.0安装DOCKER&DOCKER-COMPOSE_wd520521的博客-CSDN博客

一、(方式一)docker部署chat-web,实现自己的ChatGPT

1、创建docker-compose.yml文件

(1)在服务器上创建一个目录:chatgpt_web

mkdir chatgpt_web && cd chatgpt_web

(2)创建docker-compose.yml文件

vim docker-compose.yml

(3)以下内容填写到yml配置文件中并保存

version: '3'
services:
  app:
    image: chenzhaoyu94/chatgpt-web:latest
    ports:
      - 3002:3002
    environment:
      # api秘钥
      OPENAI_API_KEY: sk-xxx(修改为自己申请的秘钥)
      # 超时,单位毫秒,可选
      TIMEOUT_MS: 60000
保存: 按下Esc,然后输入  :wq  回车

注意:大家在编写yml文件时。要把注释删掉,否则有可能会报错。

2、部署并启动运行

docker-compose up -d

3、登录chatgpt_web页面

运行成功后直接访问(需要开放3002端口)

http://服务器ip:3002

 4、其他问题解决

(1)如果遇到 fetch failed,可以点上面的圈刷新

 如果刷新没有用的话,大家重启一下docker,然后重新启动服务

#重启docker
systemctl restart docker
#docker 启动服务

docker start 容器id

#查看容器ID

docker ps -a

5、配置反向代理 --可以不配置

nginx配置文件如下:

server

    listen 80;
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
    listen [::]:80;
    server_name 你的域名;
    location / 
		proxy_pass http://127.0.0.1:3002/;   # 注意端口号
	
    ssl_certificate    /www/m/fn.pem;
    ssl_certificate_key    /www/m/py.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

二、docker部署Chuanhu ChatGPT

1、docker 拉取镜像

docker pull tuchuanhuhuhu/chuanhuchatgpt:latest

2、启动镜像

docker run -d --name chatgpt \\
	-e my_api_key="替换成API" \\
	-e USERNAME="替换成用户名" \\
	-e PASSWORD="替换成密码" \\
	-v ~/chatGPThistory:/app/history \\
	-p 7860:7860 \\
	tuchuanhuhuhu/chuanhuchatgpt:latest

注意:(1)USERNAME 和 PASSWORD 两行可省略。若省略则不会启用认证。

(2)个人建议,省略掉USERNAME 和 PASSWORD 两行为好。

3、查看运行状态

docker logs chatgpt

 这样就可以使用IP访问了,访问链接如下

http://IP:7860

4、配置反向代理

注意配置反向代理不是必须的。如果需要使用域名,则需要配置 Nginx 反向代理。

nginx配置文件如下:

server

    listen 80;
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
    listen [::]:80;
    server_name 你的域名;

    #location部分是统一的必须一致
    location / 
		proxy_pass http://127.0.0.1:7860;   # 注意端口号
		proxy_redirect off;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Upgrade $http_upgrade;		# Websocket配置
		proxy_set_header Connection $connection_upgrade;		#Websocket配置
		proxy_max_temp_file_size 0;
		client_max_body_size 10m;
		client_body_buffer_size 128k;
		proxy_connect_timeout 90;
		proxy_send_timeout 90;
		proxy_read_timeout 90;
		proxy_buffer_size 4k;
		proxy_buffers 4 32k;
		proxy_busy_buffers_size 64k;
		proxy_temp_file_write_size 64k;
	
    #SSL部分的配置,大家可以自行配置
    ssl_certificate    /www/m/fn.pem;
    ssl_certificate_key    /www/m/py.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
server

    listen 80;
    server_name 你的域名;
    #rewrite ^(.*)$ https://$host$1 permanent;
    #return 301 https://$server_name$request_uri;
    location / 
		proxy_pass http://127.0.0.1:7860;   # 注意端口号
		proxy_redirect off;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header Upgrade $http_upgrade;		# Websocket配置
		proxy_set_header Connection $connection_upgrade;		#Websocket配置
		proxy_max_temp_file_size 0;
		client_max_body_size 10m;
		client_body_buffer_size 128k;
		proxy_connect_timeout 90;
		proxy_send_timeout 90;
		proxy_read_timeout 90;
		proxy_buffer_size 4k;
		proxy_buffers 4 32k;
		proxy_busy_buffers_size 64k;
		proxy_temp_file_write_size 64k;
	


server	
	listen       443 ssl;
	listen       [::]:443 ssl;
	server_name  你的域名;
    ssl_certificate    /www/m/fn.pem;
    ssl_certificate_key    /www/m/py.pem;
    ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置
    ssl_prefer_server_ciphers on;
	if ($scheme = http) 
        return 301 https://$server_name$request_uri;
    
	location / 
        proxy_pass http://127.0.0.1:7860;   # 注意端口号
		proxy_redirect off;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header REMOTE-HOST $remote_addr;
		proxy_set_header Upgrade $http_upgrade;		# Websocket配置
		proxy_set_header Connection $connection_upgrade;		#Websocket配置
		proxy_max_temp_file_size 0;
		client_max_body_size 10m;
		client_body_buffer_size 128k;
		proxy_connect_timeout 90;
		proxy_send_timeout 90;
		proxy_read_timeout 90;
		proxy_buffer_size 4k;
		proxy_buffers 4 32k;
		proxy_busy_buffers_size 64k;
		proxy_temp_file_write_size 64k;
    


这样就配置好nginx了,大家就可以使用自己的域名访问了。

注意(1)目前配置认证后,Nginx 必须配置 SSL,否则会出现 Cookie 不匹配问题

(2)配置好nginx后,启动nginx报错

nginx: [emerg] unknown "connection_upgrade" variable nginx: configuratio

解决方案:修改nginx.conf配置文件,向http部分添加如下配置: (这一步是为了配置websocket连接)

map $http_upgrade $connection_upgrade 
  default upgrade;
  ''      close;

docker 使用

Docker:利用Linux容器实现可移植的应用部署

Docker是一种在Linux容器里运行应用的开源工具,一种轻量级的虚拟机。除了运行应用,Docker还提供了一些工具,借助Docker Index或自己托管的Docker注册表对进行了集装箱化处理的应用进行分发,从而简化复杂应用的部署过程。

我将在本文介绍如今在部署复杂系统时公司所面临的挑战,Docker怎样有效地解决这个问题,以及Docker的其他用例。

部署的挑战

服务器应用的部署已经越来越复杂了。把几个Perl脚本拷贝到正确目录就完成服务器应用的安装,这种时代已经一去不复返了。如今的软件有很多类型的需求:

  • 对已安装软件和库的依赖(“Python版本高于2.6.3,使用Django 1.2”)

  • 依赖于正在运行的服务(“需要一个MySQL 5.5数据库和一个RabbitMQ队列”)

  • 依赖于特定的操作系统(“在64位的Ubuntu Linux 12.04上构建、测试”)

  • 资源需求:

    • 最小的可用内存(“需要1GB的可用内存”)

    • 能绑定特定的端口(“绑定80和443端口”)

我们来看一个相对简单的应用的部署:WordPress。Wordpress的安装通常要求:

  • Apache 2

  • PHP 5

  • MySQL

  • WordPress源码

  • 一个Wordpress MySQL数据库,配置Wordpress使用该数据库

  • Apache的配置:

    • 加载PHP模块

    • 支持URL重写和.htaccess文件

    • 指向WordPress源码的DocumentRoot

 
在服务器上部署、运行这样一个系统,我们可能会遇到下面的问题和挑战:

  1. 隔离性:如果我们已经在这个服务器上部署了不同的网站,已有的网站只能在nginx上运行,而Wordpress依赖于Apache,这时我们就会有麻烦:它们都监听80端口。同时运行两个网站是可以的,但需要调整配置(修改监听端口),设置反向代理等。库级别也会出现类似的冲突,如果还要运行一个仍然依赖PHP4的老应用就会出问题,因为Wordpress不再支持PHP4,同时运行PHP4和PHP5则非常困难。运行在同一个服务器上的应用没有互相隔离(在文件系统级别和网络级别),所以它们可能会互相冲突。

  2. 安全性:WordPress的安全记录并不是非常好。所以还是给它创建个沙箱,至少黑客入侵时不会影响其他运行的应用。

  3. 升级、降级:升级应用一般会覆盖现有文件。升级过程中会发生什么?系统要关闭么?如果升级失败,或者不对该怎么办?我们怎样快速回退到先前的版本?

  4. 快照、备份:一旦所有的内容都设置好,就给系统创建一个“快照”,以便能备份快照,甚至能移到另一个服务器上再次启动,或者拷贝到多个服务器上以备不时之需。

  5. 重复性:系统出新版本之后,比较好的做法是先在测试基础设施上自动部署并测试,然后再发布到生产系统。通常会利用诸如ChefPuppet等工具在服务器上自动安装一堆包,等一切内容都就绪后,再在生产系统上运行相同的部署脚本。这在百分之九十九的情况下都没有问题。但有百分之一的例外,在部署到测试环境和生产环境之间的时间跨度里,你依赖的包在包仓库里有了更新,而新版本并不兼容。结果生产环境的设置和测试环境不同,还有可能破坏生产系统。假如没有控制部署的每一个方面(例如托管自己的APT或YUM仓库),持续在多个阶段(比如测试、预演、生产环境)重复搭建出完全相同的系统就很困难。

  6. 资源限制:如果我们的Wordpress耗费CPU资源,并占用了所有的CPU周期,导致其他应用无法做任何事情怎么办?如果它用尽了全部可用的内存呢?或者疯狂写日志阻塞磁盘呢?要是能限制应用的可用资源,比如CPU、内存和磁盘空间,就会非常方便。

  7. 易于安装:也许有Debian或CentOS包,抑或是能自动执行所有复杂步骤并安装Wordpress的Chef菜谱。但这些菜谱很难稳定下来,因为它们需要考虑目标系统上可能的系统配置。很多情况下,这些菜谱只能在干净的系统上运行。因此,你不太可能更换成自己的包或Chef菜谱。这样的话,安装就是个复杂的系统工程,而不是午休期间就能搞定的事情。

  8. 易于移除:软件应该能轻松、干净地移除,不留痕迹。但部署应用通常要调整已有的配置文件、设置状态(MySQL数据库的数据,日志),完全移除应用也变得不那么容易。

那我们应该如何解决这些问题呢?

虚拟机!

我们决定在单独的虚拟机上运行独立的应用,例如Amazon的EC2,大部分问题这时会迎刃而解:

  1. 隔离性:在一个VM上安装一个应用,应用是完全独立的,除非它们攻入了对方的防火墙。

  2. 重复性:用你喜欢的方式准备系统,然后创建一个AMI。你可以随意实例化多个AMI实例。完全是可重现的。

  3. 安全性:由于我们完全隔离,如果Wordpress遭到攻击,其余的基础设施并不会受到影响——除非你没有保管好SSH密钥或者在哪里都使用同一个密码,但你应该不会这么做吧?

  4. 资源限制:VM会分配特定的CPU周期、可用内存和磁盘空间,没有加价的话就不能超额。

  5. 易于安装:越来越多的应用能够在EC2上运行,只要在AWS marketplace上点击一个按钮就能实例化应用。启动只需要几分钟,就是这样。

  6. 易于移除:不需要某个应用了?销毁VM。干净又方便。

  7. 升级、降级:Netflix如何部署代码里提到,只需要在新VM上部署新版本,然后让负载均衡器指向部署了新版本的VM。不过应用如果需要在本地保存状态,这种方法就不是很好用了。

  8. 快照、备份:点击一个按钮(或者调用一下API)就能获得EBS磁盘的快照,快照会备份到S3中。

完美!

不过……我们有个新问题:虚拟机在两个方面比较昂贵

  • 金钱:你真的有那么多钱为每个应用启动一个EC2实例?另外你能预测到需要多少个实例么?如果你以后需要更多的资源,你需要停止VM进行升级——否则就要为闲置资源白白付钱,直到真正用起来(除非你用能动态调整大小的Solaris Zones,比如Joyent上的)。

  • 时间:虚拟机相关的操作大多都很慢:启动要几分钟,捕捉快照要几分钟,创建镜像也需要几分钟。世界不停转动,我们可没有这种时间!

我们能做得更好吗?

进入Docker的世界吧。

Docker是由公共PaaS提供商dotCloud的人发起的开源项目,于去年初发起。从技术角度来说,Docker(主要用Go语言编写)试图简化两种已有技术的使用:

  • LXC:Linux容器,允许独立进程在比普通Unix进程更高的隔离级别上运行。使用的技术术语是集装箱化:一个容器里运行一个进程。容器支持的隔离级别有:

    • 文件系统:容器只能访问自己的沙箱文件系统(类似于chroot),否则要专门挂载到容器的文件系统中才能访问。

    • 用户名字空间:容器有自己的用户数据库(也就是容器的root不等于主机的root账户)。

    • 进程名字空间:只有容器里的进程才是可见的(ps aux的输出会非常简洁)。

    • 网络名字空间:每个容器都有自己的虚拟网络设备和虚拟IP(因此它可以绑定任意端口,不用占用主机端口)。

  • AUFS:高级多层的统一文件系统,可用来创建联合、写时拷贝的文件系统。

Docker可以安装在任何支持AUFS和内核版本大于等于3.8的Linux系统上。但从概念上来说它并不依赖于这些技术,以后也可以和类似的技术一起运行,例如Solaris的ZonesBSD jails,并将ZFS作为文件系统。不过目前只能选择Linux 3.8+和AUFS。

那Docker为什么有意思呢?

  • Docker非常轻量。启动VM是个大动作,需要占用大量内存;而启动Docker容器只耗费很少的CPU和内存,并且非常快。几乎和启动一个常规进程没什么区别。不仅运行容器快,构建镜像、捕获文件系统的快照也很快。

  • 它运行在已经虚拟化过的环境中。也就是说,你可以在EC2实例、Rackspace VM或VirtualBox里运行Docker。事实上,在Mac和Windows上使用Docker的首选方式是使用Vagrant

  • Docker容器能移植到任何运行Docker的操作系统上。无论是Ubuntu还是CentOS,只要Docker运行着,你的容器就能运行。

让我们回到前面的部署、操作问题列表,看看Docker是怎么解决的:

    1. 隔离性:Docker在文件系统和网络级别隔离了应用。从这个意义上来讲很像在运行”真正的“虚拟机。

    2. 重复性:用你喜欢的方式准备系统(登录并在所有软件里执行apt-get命令,或者使用Dockerfile),然后把修改提交到镜像中。你可以随意实例化若干个实例,或者把镜像传输到另一台机器,完全重现同样的设置。

  • 安全性:Docker容器比普通的进程隔离更为安全。Docker团队已经确定了一些安全问题,正在着手解决。

  • 资源约束:Docker现在能限制CPU的使用率和内存用量。目前还不能直接限制磁盘的使用情况。

  • 易于安装:Docker有一个Docker Index,这个仓库存储了现成的Docker镜像,你用一条命令就可以完成实例化。比如说,要使用Clojure REPL镜像,只要运行docker run -t -i zefhemel/clojure-repl命令就能自动获取并运行该镜像。

  • 易于移除:不需要应用了?销毁容器就行。

  • 升级、降级:和EC2 VM一样:先启动应用的新版本,然后把负载均衡器切换到新的端口。

  • 快照、备份:Docker能提交镜像并给镜像打标签,和EC2上的快照不同,Docker是立即处理的


以上是关于docker部署chat-web,实现自己的ChatGPT的主要内容,如果未能解决你的问题,请参考以下文章

Ubuntu中安装jenkins+docker,实现项目部署

Docker 简介下载安装

docker+githook实现goweb项目自动发包部署

使用Dockerfile定制自己的docker镜像

docker 使用

在CentOS中安装Docker