这里假设你已经看过了 「AI Demo 快速部署」 ,对 AI Demo 的源码和部署流程有了一定的了解。
假设你已经准备好所有资源:
域名:demo.example.ai 和 registry.example.ai
服务器 IP:12.23.34.45
服务器 OS:ubuntu server 22.04
我们继续使用那个简单的 Gradio 搭建的 Chatbot,源码见 chatbot-by-gradio 。
0 方案概览
方案 A(服务器构建/服务器运行) 是最简单的方法,但是需要服务器有较好的性能,否则构建镜像会非常慢。
方案 B(本地构建/推送远程仓库/服务器运行) 是最复杂的方法,但是可以解决服务器性能较差的问题,以及多人协作起来更加方便。
方案 C(本地构建/手动上传/服务器运行) 是最通用的方法,也可以解决服务器性能较差的问题,但是需要手动上传镜像。
1 docker 配置 首先要把部署的配置文件准备好,不管哪种方案都是要用到的。
1.1 Dockerfile 我们通过编写一个 docker 构建的配置文件来打包,这个文件一般被命名为 Dockerfile,放在项目的根目录下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 FROM python:3.11 .10 -alpineWORKDIR /workspace COPY . . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple EXPOSE 7860 CMD ["python" , "run.py" ]
1.2 .dockerignore 这个文件的作用是告诉 Docker 在构建镜像时需要忽略哪些文件或目录。(它基本等同于 .gitignore 文件 + .git 目录)
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 # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ # pycharm .idea/ # setup files.txt # vscode .vscode # mac os .DS_Store # git .git/
2 方案 A(服务器构建/服务器运行) 我们直接在服务器上构建镜像,然后使用镜像运行容器即可。
2.1 构建镜像 1 2 3 4 5 6 7 8 ssh root@12.23.34.45 cd /root/workspace/chatbot-by-gradiogit pull docker build -t chatbot-by-gradio:1.0.0 .
2.2 运行容器 1 2 3 4 5 docker run -d --name chatbot-by-gradio \ -p 7860:7860 chatbot-by-gradio:1.0.0 docker logs -f chatbot-by-gradio
3 方案 B(本地构建/推送远程仓库/服务器运行) 我们使用 docker registry 来存储镜像,这样就可以在任意的地方(比如本地有较好的硬件资源)进行打包,然后在部署服务器(性能较差)上进行部署。
3.1 部署 registry 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 ssh root@12.23.34.45 mkdir -p /root/data/registry/authdocker run --rm --entrypoint htpasswd httpd:2 -Bbn admin qwer1234 > /root/data/registry/auth/htpasswd docker run -d -p 5000:5000 --restart=always --name=registry \ -v /root/data/registry/auth:/auth \ -v /root/data/registry/:/var/lib/registry/ \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ registry:2.8.3 certbot certonly --standalone -d "registry.example.ai" vim /etc/nginx/sites-available/registry.example.ai server { listen 80; listen [::]:80; server_name registry.example.ai; rewrite ^(.*)$ https://registry.example.ai:443$1 permanent; } server { listen 443 ssl; listen [::]:443 ssl; ssl_certificate /etc/letsencrypt/live/registry.example.ai/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.example.ai/privkey.pem; keepalive_timeout 70; server_name registry.example.ai; server_tokens off; fastcgi_param HTTPS on; fastcgi_param HTTP_SCHEME https; client_max_body_size 1G; chunked_transfer_encoding on; location / { proxy_pass http://127.0.0.1:5000; 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 X-Forwarded-Proto $scheme ; proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; send_timeout 300; } } nginx_ensite registry.example.ai service nginx reload
完成上述配置后,你就可以在本地打包,然后推送到远程仓库了。
3.2 本地打包
⚠️:请注意:apple 芯片的 mac,请不要再本地电脑打包,请去服务器上打包!因为容器镜像和硬件架构有关,arm 架构的无法运行在 x86 架构上,其实大多数机器都是 x86 架构,我们能碰到的 arm 架构就是 apple 芯片(m 系列)的 mac!
1 2 3 4 5 cd /root/workspace/chatbot-by-gradiodocker build -t registry.example.ai/chatbot-by-gradio:1.0.0 .
3.3 推送镜像到远程仓库 1 2 3 4 5 6 7 docker login registry.example.ai docker push registry.example.ai/chatbot-by-gradio:1.0.0
3.4 部署服务器上拉取镜像 1 2 3 4 5 6 7 8 9 10 11 12 ssh root@12.23.34.45 docker pull registry.example.ai/chatbot-by-gradio:1.0.0 docker run -d --name chatbot-by-gradio -p 7860:7860 \ registry.example.ai/chatbot-by-gradio:1.0.0 docker logs -f chatbot-by-gradio
这样就可以在任意地方打包,然后推送到远程仓库,然后在部署服务器上拉取镜像并运行容器了。
PS. 还可以准备一个专门用于打包的高性能构建服务器,然后使用方案 B 进行打包,然后推送到远程仓库,然后在部署服务器上拉取镜像并运行容器。
4 方案 C(本地构建/手动上传/服务器运行) 不使用镜像仓库,靠 scp 把镜像以文件的方式上传到服务器,然后运行容器。
4.1 本地构建 1 2 3 4 cd /root/workspace/chatbot-by-gradiodocker build -t chatbot-by-gradio:1.0.0 .
4.2 手动上传镜像 1 2 3 4 5 docker save chatbot-by-gradio:1.0.0 > chatbot-by-gradio.tar scp chatbot-by-gradio.tar root@12.23.34.45:/root/workspace/chatbot-by-gradio
4.3 服务器上运行容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ssh root@12.23.34.45 cd /root/workspace/chatbot-by-gradiodocker load < chatbot-by-gradio.tar docker images chatbot-by-gradio docker run -d --name chatbot-by-gradio -p 7860:7860 \ chatbot-by-gradio:1.0.0 docker logs -f chatbot-by-gradio
5 参考