1.双容器部署Django+Uwsgi+Nginx项目示意图

dcoker 部署nginx docker部署django nginx_django

  • 1.用户通过客户端访问服务器的80端口,请求由宿主机80端口映射到Nginx所在的容器1。
  • 2.Nginx接收到请求后会判断请求是静态的还是动态的,静态文件请求自己处理,动态请求则转发给Django+Uwsgi所在端口为8000的容器。
  • 3.注意:多容器创建和启动的先后顺序很重要,因为存在依赖关系

2.双容器部署Django+Uwsgi+Nginx代码布局图

  • 由于之前项目中已经存在了一个Dockerfile,所以如果将nginx的Dockerfile也放在这里,显然是不合适的,所以我们需要调整项目目录结构,在项目目录下新建compose文件夹,专门存放用于创建其它镜像的Dockerfile及配置文件,后面我们会将项目数据库由sqlite替换为mysql,到时候mysql也将会是一个独立的容器。
docker_django
├── compose
│   └── nginx
│       ├── Dockerfile  # nginx镜像需要用到的Dockerfile
│       └── nginx.conf
├── db.sqlite3
├── docker_django
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── Dockerfile  # django+uwsgi镜像需要用到的Dockerfile
├── manage.py
├── requirements.txt
├── start.sh
├── static
├── uwsgi.ini
└── uwsgi.log
1.准备工作
  • 由于需要nginx和uwsgi进行通信,所以需要修改uwsgi.ini文件连接方式
# http = 0.0.0.0:8000
socket = 0.0.0.0:8000
2.重新构建Django+uwsgi镜像
  • /var/www/html/docker_django/Dockerfile
# 进入项目目录下的Dockerfile创建名为django_docker_new的镜像,版本v1,.代表当前目录
sudo docker build -t django_uwsgi_img:v1 .
# 启动并运行容器django_docker_new, -d为后台运行,-v进行目录挂载 宿主机目录:容器目录。
sudo docker run -it --name django_uwsgi -p 8000:8000 -v /var/www/html/docker_django:/var/www/html/docker_django -d django_uwsgi_img:v1
# 查看容器是否运行
sudo docker ps
# 查看容器django_docker_new的IP地址
sudo docker inspect django_uwsgi | grep "IPAddress"
[root@localhost nginx]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
django_uwsgi_img    v1                  59ed539e2b97        2 minutes ago       988 MB
docker.io/centos    centos7             b5b4d78bc90c        5 weeks ago          203 MB

[root@localhost docker_django]# sudo docker inspect django_uwsgi | grep "IPAddress"
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",
  • 说明:

启动运行容器时一定要考虑目录挂载,防止数据丢失。我们的项目在容器中的路径是/var/www/docker_django,用户产生的数据也存储在这个容器内。我们一但删除容器,那么容器内的数据也随之丢失了,即使重新创建容器数据也不会回来。

通过-v参数可进行目录挂载。冒号前为宿主机目录,冒号后为镜像容器内挂载的路径,两者必须为绝对路径。如果没有指定宿主机的目录,则容器会在/var/lib/docker/volumes/随机配置一个目录。

本例中我们使用了-v参数把容器中的目录/var/www/docker_django挂载到了宿主机的的目录/var/www/docker_django上,实现了两者数据的同步。此时删除容器不用担心,数据会在宿主机上有备份。

3.创建容器Nginx的镜像并启动运行容器
  • /var/www/html/docker_django/compose/nginx/Dockerfile
FROM nginx:latest

# 镜像维护者
MAINTAINER Fat Puffer <dcpuffer@outlook.com>

# 将项目nginx配置文件拷贝到nginx配置文件目录下
ADD nginx.conf /etc/nginx/conf.d/

# sed是一个Linux编辑器吧,此命令的作用是查找文件/etc/nginx/nginx.conf中包含user的行,并将此行的nginx替换成root
RUN sed -i '/user/{s/nginx/root/}' /etc/nginx/nginx.conf

# 删除原有配置文件,创建静态资源文件夹和ssl证书保存文件夹
RUN rm /etc/nginx/conf.d/default.conf \
 && mkdir -p /usr/share/nginx/html/static \
 && mkdir -p /usr/share/nginx/html/media \
 && mkdir -p /usr/share/nginx/ssl

CMD ["nginx", "-g", "daemon off;"]
  • /var/www/html/docker_django/compose/nginx/nginx.conf
# nginx配置文件。
upstream django {
    ip_hash;  # 负载策略
    server 172.17.0.2:8000; # Django+uwsgi容器所在IP地址及开放端口,非宿主机外网IP
}
 
server {
    listen 80; # 监听80端口
    server_name localhost; # 可以是nginx容器所在ip地址或127.0.0.1,不能写宿主机外网ip地址
    location /static {
        alias /usr/share/nginx/html/static; # 静态资源路径
    }
 
    location /media {
        alias /usr/share/nginx/html/media; # 媒体资源,用户上传文件路径
    }
 
    location / {
        include /etc/nginx/uwsgi_params;
        uwsgi_pass django;
        uwsgi_read_timeout 600;
        uwsgi_connect_timeout 600;
        uwsgi_send_timeout 600;
        # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # proxy_set_header Host $http_host;
        # proxy_redirect off;
        # proxy_set_header X-Real-IP  $remote_addr;
        # proxy_pass http://django;    
    }
}
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
  • 构建容器:注意构建命令目录(/var/www/docker_django/compose/nginx/nginx.conf),别搞错了
# 进入nginx目录, 使用该目录下的Dockerfile创建名为django_nginx_img的镜像,版本v1,.代表当前目录
sudo docker build -t django_nginx_img:v1 .
  • 查看镜像
[root@localhost nginx]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
django_nginx_img    v1                  9aea6a626209        11 seconds ago      132 MB
django_uwsgi_img    v1                  59ed539e2b97        5 minutes ago       988 MB
docker.io/nginx     latest              2622e6cca7eb        15 hours ago        132 MB
docker.io/centos    centos7             b5b4d78bc90c        5 weeks ago         203 MB
  • 使用镜像创建容器
# 启动并运行容器django_docker_new, -d为后台运行,宿主机与Nginx端口映射为80:80。Nginx下的static和media目录挂载到宿主机的Django项目下的media和static文件夹。
sudo docker run -it -p 80:80 --name django_nginx \
 -v /var/www/html/docker_django/static:/usr/share/nginx/html/static \
 -v /var/www/html/docker_django/media:/usr/share/nginx/html/media \
 -v /var/www/html/docker_django/compose/nginx/nginx.log:/var/log/nginx \
 -d django_nginx_img:v1
  • 查看容器
[root@localhost nginx]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                    NAMES
a1777509d287        django_nginx_img:v1   "/docker-entrypoin..."   3 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp       django_nginx
cbe594124cd4        django_uwsgi_img:v1   "/bin/bash"              4 minutes ago       Up 4 minutes        0.0.0.0:8000->8000/tcp   django_uwsgi
[root@localhost nginx]#
4. 进入Django+UWSGI容器执行Django命令并启动uwsgi服务器
sudo docker exec -it django_uwsgi /bin/bash start.sh
[root@localhost nginx]# sudo docker exec -it django_uwsgi /bin/bash start.sh
No changes detected
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.
No changes detected
[uWSGI] getting INI configuration from /var/www/html/docker_django/uwsgi.ini
[uwsgi-static] added mapping for /static => /var/www/html/docker_django/static
[root@localhost nginx]#
5. 打开浏览器访问
http://10.10.102.238/admin/

dcoker 部署nginx docker部署django nginx_dcoker 部署nginx_02

3.部署过程中的错误

1. nginx 502错误
  • 1.进入容器查看错误日志,错误如果出现在upstream转发到uwsgi接口上,请检查uwsgi配置文件配置信息是否正确,最简单的办法,就是退出容器,在你项目下直接使用uwsgi --ini uwsgi.ini尝试启动,看看哪里有问题
  • 2.如果问题是Forbidden,有可能是nginx启动用户的权限不足(etc/nginx/nginx.conf),需要将user nginx;修改为user root;,在构建nginx镜像时,Dockerfile中需要添加这条命令RUN sed -i '/user/{s/nginx/root/}' /etc/nginx/nginx.conf
2. Bad Request (400)
  • 检查项目配置文件settings.pyALLOWED_HOSTS,此处需要设置为物理机真实IP