如何将配置Docker的Django项目成功部署到Ubuntu服务器
Django项目Docker+Ansible Ubuntu服务器部署方案
一、先修正项目配置缺陷
现有配置存在几个服务器环境适配问题,直接部署会失败:
- Django数据库配置未指定容器内数据库地址,默认连localhost会找不到PostgreSQL服务
depends_on仅控制容器启动顺序,不等待PostgreSQL服务初始化完成,web服务启动时会因数据库未就绪直接崩溃- 缺少psycopg2依赖的系统库,构建镜像时容易报错
- 未配置服务启动前自动执行数据库迁移、静态文件收集,上线后会发表不存在、静态资源404
- 用绑定挂载存数据库数据,服务器环境容易出现权限问题
修正后的Dockerfile
# syntax=docker/dockerfile:1 FROM python:3 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 # 安装PostgreSQL客户端和依赖库,解决psycopg2安装、数据库连接报错 RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client libpq-dev && rm -rf /var/lib/apt/lists/* WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/ # 启动前自动执行迁移、收集静态文件,再启动服务 CMD ["sh", "-c", "python manage.py migrate && python manage.py collectstatic --noinput && python manage.py runserver 0.0.0.0:80"]
修正后的docker-compose.yml
version: "3.9" services: db: image: postgres:15 # 固定大版本,避免latest标签拉取新版本导致兼容问题 volumes: - postgres_data:/var/lib/postgresql/data # 用Docker命名卷存储数据,权限更稳定 environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres # 生产环境请替换为强密码,建议通过.env文件注入不要硬编码 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 web: build: . ports: - "80:80" environment: - POSTGRES_NAME=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_HOST=db # 必须配置,指定数据库服务的容器内网地址 - DEBUG=0 # 生产环境关闭Debug模式 - ALLOWED_HOSTS=* # 替换为实际的服务器公网IP或绑定域名 depends_on: db: condition: service_healthy # 等数据库健康检查通过后再启动web服务 volumes: postgres_data:
注意:确认Django项目的
settings.py中数据库配置读取上述环境变量,参考配置:import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('POSTGRES_NAME'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': os.environ.get('POSTGRES_HOST', 'localhost'), 'PORT': 5432, } }
二、编写Ansible部署剧本
之前部署失败基本是因为目标机没装Docker环境、目录权限不对、代码同步不全导致的,直接用下面的playbook即可,前提是本地Ansible控制端已经能通过SSH免密登录目标Ubuntu服务器。在项目根目录新建deploy.yml:
- name: 部署Django Docker项目 hosts: django_server # 替换为你inventory中配置的目标服务器组名/IP become: true tasks: # 安装系统基础依赖 - name: 安装必要工具包 apt: name: - apt-transport-https - ca-certificates - curl - gnupg - lsb-release update_cache: true # 配置Docker源 - name: 导入Docker GPG密钥 shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg args: creates: /usr/share/keyrings/docker-archive-keyring.gpg - name: 写入Docker软件源配置 shell: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null args: creates: /etc/apt/sources.list.d/docker.list # 安装Docker和Compose插件 - name: 安装Docker引擎与Docker Compose apt: name: - docker-ce - docker-ce-cli - containerd.io - docker-compose-plugin update_cache: true # 配置Docker开机自启 - name: 启动Docker服务并设置开机自启 systemd: name: docker enabled: true state: started # 创建部署目录 - name: 创建项目部署目录 file: path: /opt/django-app state: directory owner: ubuntu # 替换为你服务器登录的用户名 group: ubuntu mode: '0755' # 同步代码到服务器 - name: 同步本地项目代码 synchronize: src: ./ dest: /opt/django-app rsync_opts: - "--exclude=.git" - "--exclude=__pycache__" - "--exclude=*.pyc" - "--exclude=data/" # 修复目录权限 - name: 设置项目目录权限 file: path: /opt/django-app state: directory recurse: true owner: ubuntu group: ubuntu # 启动服务 - name: 构建镜像并启动容器 community.docker.docker_compose_v2: project_src: /opt/django-app build: always state: present pull: always
三、执行部署
- 先在本地Ansible的inventory文件(默认路径
/etc/ansible/hosts)中添加目标服务器配置:
[django_server] 你的服务器公网IP ansible_user=ubuntu ansible_ssh_private_key_file=本地SSH私钥文件路径
- 在项目根目录执行部署命令:
ansible-playbook deploy.yml - 部署完成后等待10秒左右,直接访问服务器公网IP即可打开Django站点。
常见问题排查
- 80端口无法访问:先检查服务器安全组是否放开80端口入站规则,Ubuntu本机可执行
ufw allow 80放行防火墙端口 - 容器启动失败:登录服务器进入
/opt/django-app目录,执行docker compose logs web查看具体报错,常见原因是数据库配置错误、Python依赖缺失 - 后续代码更新:直接重新执行
ansible-playbook deploy.yml即可,剧本会自动重新构建镜像、重启服务
内容的提问来源于stack exchange,提问作者Grigorkos
相关产品推荐
相关产品推荐

