标签: docker

  • nginx反代docker版Streamlit 应用

    nginx反代docker试了很久总是出错,但是不用nginx反代直接运行则运行正常,尝试很久才明白原因。

    这其实是 Streamlit 特有的问题
    它默认认为自己直接对外服务(host 为 localhost,WebSocket 直接连自己的8501端口),所以一旦你反向代理,Streamlit里前端的WebSocket就失效了。

    为什么出错?

    Streamlit前端会自动尝试建立 WebSocket连接,比如:

    1
    wss://sub.yourdoman.com/_stcore/stream
    
    
    
    
    

    但它不知道你用的是 wss(HTTPS+WebSocket),而且路径前缀也会错,导致连不上。

    Streamlit反代时,必须加一些额外配置:


    解决方案

    修改你的 docker-compose,在 ndsri-ai-calculator 容器启动时加环境变量(或者加启动参数),告诉Streamlit:

    1.dock-compose.yml

    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
    services:
        your_app:
          container_name: your_app
          image: yourusername/your_app:latest
          networks:
            - test_network
          restart: always
          depends_on:
            - test_nginx
          environment:
            - STREAMLIT_SERVER_ENABLECORS=false
            - STREAMLIT_SERVER_ENABLEWEBSOCKETCOMPRESSION=false
            - STREAMLIT_SERVER_HEADLESS=true
            - STREAMLIT_SERVER_BASEURLPATH=""
            - STREAMLIT_SERVER_PORT=8501
            - STREAMLIT_SERVER_ADDRESS=0.0.0.0
            - STREAMLIT_SERVER_USEWEBSOCKET=true
        #如果镜像里已经默认 streamlit run了,环境变量就够了,不需要额外加 command。
        #command: ["streamlit", "run", "your_app.py", "--server.port=8501", "--server.address=0.0.0.0", "--server.enableCORS=false", "--server.enableWebsocketCompression=false", "--server.headless=true"]
          test_nginx:
            container_name: test_nginx
            image: nginx:latest
            volumes:
              - /etc/nginx/ssl:/etc/nginx/ssl
              - ./nginx.conf:/etc/nginx/nginx.conf
            ports:
              - "80:80"
              - "443:443"
            networks:
              - test_network
          
        networks:
          test_network:
            name: test_network

    2.nginx.conf配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    server {
        listen 443 ssl;
        server_name sub.yourdomain.com;
        ssl_certificate /etc/nginx/ssl/yourdomain.crt;
        ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
     
        location / {
            proxy_pass http://yourapp:8501;
            proxy_http_version 1.1;
            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_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_redirect off;
            proxy_buffering off;
        }
    }

    3.nginx.conf配置

    运行docker,重启nginx(如果之前已安装)

    1
    2
    3
    docker-compose up -d
    #若只重置或者运行
    docker restart test_nginx

  • 制作docker并上传至Docker Hub

    1.安装docker

    运行以下命令安装docker并查看docker版本,确认docker是否安装成功。

    1
    2
    3
    4
    5
    6
    #以root运行就不需要写sudo
    sudo apt-get update
    sudo apt-get install -y docker.io
    sudo systemctl start docker
    sudo systemctl enable docker
    docker --version

    2.准备应用,编写docker环境

    2.1 新建文件夹,将准备好Streamlit 应用代码

    ndsri_ai_calculator_optimized.py放入文件夹内,并在文件夹内新建Dockerfile和requirements.txt。

    1
    2
    3
    4
    5
    project_folder/
    ├── ndsri_ai_calculator_optimized.py
    ├── Dockerfile
    └── requirements.txt

    2.2根据Streamlit环境编写Dockerfile和requirements.txt

    2.2.2Dockerfile

    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
    # 使用官方Python基础镜像(基于Debian)
    FROM python:3.12-slim
     
    # 设置工作目录
    WORKDIR /project
     
    # 复制应用代码到容器中
    COPY your_app.py .
    COPY requirements.txt .
     
    # 安装系统依赖(RDKit和绘图功能需要)
    RUN apt-get update && apt-get install -y \
        build-essential \
        libopenblas-dev \
        libxrender1 \
        libxext6 \
        libfontconfig1 \
        libcairo2 \
        && rm -rf /var/lib/apt/lists/*
     
    # 安装Python依赖
    RUN pip install --no-cache-dir -r requirements.txt
     
    # 暴露Streamlit默认端口
    EXPOSE 8501
     
    # 运行Streamlit应用
    CMD ["streamlit", "run", "your_app.py", "--server.port=8501", "--server.address=0.0.0.0"]

    注:RDKit所需包名及作用,不加运行代码时会出错

    包名主要作用在RDKit中的应用场景未来可能扩展用途
    build-essentialC/C++编译工具链编译RDKit源码优化、自定义模块开发
    libopenblas-dev高效矩阵运算库分子力场、3D构象计算大规模特征计算、机器学习
    libxrender12D图形渲染加速分子图绘制Web服务分子展示
    libxext6X11图形扩展支持分子图生成无头服务器绘图
    libfontconfig1字体管理元素符号标注高质量分子图输出
    libcairo22D图形绘制库生成PNG、SVG、PDF分子图自动化图像生成、报告制作

    2.2.3 requirements.txt

    内容为代码中需使用的包及版本

    1
    2
    3
    4
    streamlit==1.44.0
    rdkit==2024.9.6
    pandas==2.2.3
    numpy==1.26.4

    注:pandas依赖于numpy,不装numpy会报错。

    3.构建 Docker 镜像

    构建docker

    1
    docker build -t your_app .

    运行容器

    1
    2
    docker images #列出本地镜像,用于检查镜像是否正确建立
    docker run -d -p 8501:8501 your_app #运行docker镜像,确认能否正常

    4.上传docker

    4.1 新建docker账户

    进入https://hub.docker.com/新建账户并验证邮箱

    4.2上传docker

    1
    2
    3
    4
    5
    6
    #1.输入账户名和密码登录Docker Hub
    docker login
    #2.为镜像打标签,yourusername为Docker Hub的用户名
    docker tag your_app:latest yourusername/your_app:latest
    #3.将镜像推送到Docker Hub
    docker push yourusername/your_app:latest

  • 使用docker安装wordpress套装

    1.前期准备

    1.准备一个域名,并解析至cloudflare,设置好A记录及AAAA记录。

    2.申请证书

    在cloudflare中申请此域名的证书(包括域名*.yourdomain.com和www.yourdomain.com),并将公钥和私钥保存好。

    2.docker-compose.yml配置

    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
    services:
      test_mysql:
        container_name: test_mysql
        image: mysql:latest
        volumes:
          - mysql_data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: ${WORDPRESS_DB_PASSWORD}
        networks:
          - test_network
     
      test_wordpress:
        container_name: test_wordpress
        image: wordpress:latest
        volumes:
          - wordpress_data:/var/www/html/wp-content
        environment:
          WORDPRESS_DB_HOST: test_mysql
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
          WORDPRESS_DB_NAME: wordpress
        networks:
          - test_network
        depends_on:
          - test_mysql
     
      test_phpmyadmin:
        container_name: test_phpmyadmin
        image: phpmyadmin:latest
        environment:
          PMA_HOST: test_mysql
          PMA_ARBITRARY: 1 # 允许用户选择服务器并手动登录
        networks:
          - test_network
        depends_on:
          - test_mysql
     
      test_redis:
        container_name: test_redis
        image: redis:latest
        networks:
          - test_network
     
      test_nginx:
        container_name: test_nginx
        image: nginx:latest
        volumes:
          - /etc/nginx/ssl:/etc/nginx/ssl
          - ./nginx.conf:/etc/nginx/nginx.conf
        ports:
          - "80:80"
          - "443:443"
        networks:
          - test_network
        depends_on:
          - test_wordpress
          - test_phpmyadmin
     
    networks:
      test_network:
        name: test_network
     
    volumes:
      mysql_data:
      wordpress_data:

    3.nginx.conf配置文件

    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
    user nginx;
    worker_processes auto;
     
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;
     
    events {
        worker_connections 1024;
    }
     
    http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
     
        log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
     
        access_log /var/log/nginx/access.log main;
     
        sendfile on;
        keepalive_timeout 65;
     
        # 默认 server 块
        server {
            listen 443 ssl;
            server_name _;
            ssl_certificate /etc/nginx/ssl/yourdomain.crt;
            ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
            return 444;
        }
     
        # HTTP 到 HTTPS 重定向
        server {
            listen 80;
            server_name yourdomain.com www.yourdomain.com
            return 301 https://$host$request_uri;
        }
     
        # 主网站 (WordPress)
        server {
            listen 443 ssl;
            server_name yourdomain.com www.yourdomain.com;
            ssl_certificate /etc/nginx/ssl/yourdomain.crt; #公钥
            ssl_certificate_key /etc/nginx/ssl/yourdomain.key; #私钥
     
            location /phpmyadmin/ {
                proxy_pass http://site_phpmyadmin/;
                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_redirect off;
                proxy_buffering off;
            }
     
            location / {
                proxy_pass http://site_wordpress;
                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;
            }
        }
     
    }

    4.运行安装所有docker

    1
    docker-compose up -d

    5.进入www.youdomain.com安装wordpress。

    6.进入www.youdomain.com/phpmyadmin可直接操作数据库