Dockerfile 部署uwsgi+nginx+django

背景

最近在和组内小伙伴一起写接口测试平台后端,使用的是 drf 框架,目前已经完成部分工作。在和前端联调试另一个小伙伴使用 uwsgi 部署起来了,我感觉这样部署很 low,因为之前有了解过 docker 所以想着这一次彻底把 docker 给学会吧,于是就有了这篇文章。

首先先看一下我的目录结构

image.png

想法

我计划使用两个镜像来部署我的项目,一个来部署 django+uwsgi 项目,一个来运行 nginx,两个镜像均使用 Dockerfile。所以前提肯定是先把 docker 下载好,再编写好两个镜像。

nginx 文件

1. 编写 nginx 的 Dockerfile
FROM nginx

COPY nginx.conf /etc/nginx/nginx.conf

CMD ["nginx", "-g", "daemon off;"]

2. 编写 nginx.conf 文件
#user  nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid       logs/nginx.pid;


events {
  worker_connections 1024;
}


http {
  include 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 logs/access.log main;

  sendfile       on;
  #tcp_nopush     on;

  #keepalive_timeout 0;
  keepalive_timeout 65;

  #gzip on;

  server {
      listen       8080;
      server_name localhost;

      #charset koi8-r;

      #access_log logs/host.access.log main;

      location / {
          root   html;
          index index.html index.htm;
          uwsgi_pass maas:8001;
          include uwsgi_params;
      }
  location /static {
          alias /backend/static;
       
  }

      #error_page 404             /404.html;

      # redirect server error pages to the static page /50x.html
      #
      error_page   500 502 503 504 /50x.html;
      location = /50x.html {
          root   html;
      }

      # proxy the PHP scripts to Apache listening on 127.0.0.1:80
      #
      #location ~ \.php$ {
      #   proxy_pass   http://127.0.0.1;
      #}

      # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
      #
      #location ~ \.php$ {
      #   root           html;
      #   fastcgi_pass   127.0.0.1:9000;
      #   fastcgi_index index.php;
      #   fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
      #   include       fastcgi_params;
      #}

      # deny access to .htaccess files, if Apache's document root
      # concurs with nginx's one
      #
      #location ~ /\.ht {
      #   deny all;
      #}
  }


  # another virtual host using mix of IP-, name-, and port-based configuration
  #
  #server {
  #   listen       8000;
  #   listen       somename:8080;
  #   server_name somename alias another.alias;

  #   location / {
  #       root   html;
  #       index index.html index.htm;
  #   }
  #}


  # HTTPS server
  #
  #server {
  #   listen       443 ssl;
  #   server_name localhost;

  #   ssl_certificate     cert.pem;
  #   ssl_certificate_key cert.key;

  #   ssl_session_cache   shared:SSL:1m;
  #   ssl_session_timeout 5m;

  #   ssl_ciphers HIGH:!aNULL:!MD5;
  #   ssl_prefer_server_ciphers on;

  #   location / {
  #       root   html;
  #       index index.html index.htm;
  #   }
  #}
  include servers/*;
}


Django 项目所需文件

1. 编写 Dockerfile
FROM centos:7
MAINTAINER shd
RUN yum install -y gcc gcc-c++ make vie git libffi-devel \
openssl-devel pcre-devel gd-devel \
iproute net-tools telnet wget curl initscripts psmisc && \
yum clean all && \
rm -rf /var/cache/yum/*
COPY pythons/Python-3.8.2.tar.xz Python-3.8.2.tar.xz
RUN tar -xvJf Python-3.8.2.tar.xz
RUN cd Python-3.8.2 && \
./configure prefix=/usr/local/python3 && \
make && make install && \
cd .. && rm -rf /Python-3.8.2* && \
  rm -rf /usr/bin/python && \
  ln -s /usr/local/python3/bin/python3 /usr/bin/python && \
  ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
RUN set -ex \
  && sed -i "s#/usr/bin/python#/usr/bin/python2.7#" /usr/bin/yum \
  && sed -i "s#/usr/bin/python#/usr/bin/python2.7#" /usr/libexec/urlgrabber-ext-down \
  && yum install -y deltarpm \
  && pip install --upgrade pip

RUN pip install uwsgi && \
      ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi

COPY requirements.txt backend/requirements.txt
WORKDIR backend
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
EXPOSE 8001
EXPOSE 9191

#ENTRYPOINT ["/usr/bin/uwsgi", "uwsgi.ini"]
#CMD ["/bin/bash"]
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

#CMD ["/usr/bin/uwsgi", "uwsgi.ini"]


2. entrypoint.sh
#!/bin/bash

uwsgi uwsgi.ini
sleep 10000000 # 因为启动容器后,总是会自动停止,因此先使用笨办法让容器sleep来避免容器停止,后续想办法解决

3. uwsgi.ini
[uwsgi]
http= 0.0.0.0:8005
socket= :8001
chdir= /backend
wsgi-file= backend/wsgi.py
static-map= /static=/backend/static
master= 1
workers= 7
vacuum= true
uid= root
gid= root
pidfile= /backend/backend-uwsgi.pid
daemonize= /backend/uwsgi.log

构造镜像,启动容器

1. 新创建一个网络

  因为涉及到两个容器,并且容器每次启动后 ip 都会变,所以为了避免这种问题就需要自定义容器网络。 容器一共有 4 种网络模式,host、none、container、bridge,默认是 bridge 模式。因此我们自定义网络也最好使用 bridge 模式,并且自定义的网络可以解决容器启动 ip 变更后,无法通信的问题。

(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker network create --subnet=166.156.0.0/16 --gateway=166.156.0.1 shdnet 
e2f658e77a46f4a0140cf25cf6265ba12641b0fd6ced24a183379d14f455e1c6
(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker network ls
NETWORK ID     NAME     DRIVER   SCOPE
e8be82af8b3a   bridge   bridge   local
1274d320a029   host     host     local
c7c913872b2d   mynets   bridge   local
bd6d8d7b314c   none     null     local
e2f658e77a46   shdnet   bridge   local
(maas_backend_env) shd:maas_qa_backend shenhaodong$


2. 构建项目镜像并使用自定义网络启动

因为 nginx 容器依赖项目的镜像,所以需要先启动项目容器才可以去启动 nginx 容器,具体可以参考 nginx 的配置文件,

  uwsgi_pass maas:8001; #容器名字+端口号

  • 构建镜像

(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker build . -t centos:v1
[+] Building 1.8s (17/17) FINISHED                                                                                                                                                                                
=> [internal] load build definition from Dockerfile                                                                                                                                                         0.0s
=> => transferring dockerfile: 1.33kB                                                                                                                                                                       0.0s
=> [internal] load .dockerignore                                                                                                                                                                           0.0s
=> => transferring context: 2B                                                                                                                                                                             0.0s
=> [internal] load metadata for docker.io/library/centos:7                                                                                                                                                 1.2s
=> [internal] load build context                                                                                                                                                                           0.4s
=> => transferring context: 17.88MB                                                                                                                                                                         0.4s
=> [ 1/12] FROM docker.io/library/centos:7@sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e                                                                                         0.0s
=> CACHED [ 2/12] RUN yum install -y gcc gcc-c++ make vie git libffi-devel openssl-devel pcre-devel gd-devel iproute net-tools telnet wget curl initscripts psmisc && yum clean all && rm -rf /var/cache/y 0.0s
=> CACHED [ 3/12] COPY pythons/Python-3.8.2.tar.xz Python-3.8.2.tar.xz                                                                                                                                     0.0s
=> CACHED [ 4/12] RUN tar -xvJf Python-3.8.2.tar.xz                                                                                                                                                       0.0s
=> CACHED [ 5/12] RUN cd Python-3.8.2 && ./configure prefix=/usr/local/python3 && make && make install && cd .. && rm -rf /Python-3.8.2* &&     rm -rf /usr/bin/python &&     ln -s /usr/local/python3/bin 0.0s
=> CACHED [ 6/12] RUN set -ex     && sed -i "s#/usr/bin/python#/usr/bin/python2.7#" /usr/bin/yum     && sed -i "s#/usr/bin/python#/usr/bin/python2.7#" /usr/libexec/urlgrabber-ext-down     && yum install 0.0s
=> CACHED [ 7/12] RUN pip install uwsgi &&     ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi                                                                                                           0.0s
=> CACHED [ 8/12] COPY requirements.txt maas_qa_backend/requirements.txt                                                                                                                                   0.0s
=> CACHED [ 9/12] WORKDIR maas_qa_backend                                                                                                                                                                   0.0s
=> CACHED [10/12] RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple                                                                                                           0.0s
=> CACHED [11/12] COPY entrypoint.sh /entrypoint.sh                                                                                                                                                         0.0s
=> CACHED [12/12] RUN chmod +x /entrypoint.sh                                                                                                                                                               0.0s
=> exporting to image                                                                                                                                                                                       0.0s
=> => exporting layers                                                                                                                                                                                     0.0s
=> => writing image sha256:34d6ab3660afcbef63792eb6b4a79f5ec8d30f65e7f79e04625ae22514a4cc74                                                                                                                 0.0s
=> => naming to docker.io/library/centos:v1

  • 启动容器,并且起名为 maas

shd:maas_qa_backend shenhaodong$ docker run -itd -p 8008:8001 -p8006:8005 -v /Users/shenhaodong/PycharmProjects/maas_qa_backend:/backend --net shdnet --name maas 34d6ab3660af
dba395715a34ab4d8355687c1d83e81134b519e579ca3c86052957921121b3b2
(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker ps
CONTAINER ID   IMAGE         COMMAND           CREATED         STATUS         PORTS                                                     NAMES
dba395715a34   34d6ab3660af   "/entrypoint.sh"   4 seconds ago   Up 3 seconds   9191/tcp, 0.0.0.0:8008->8001/tcp, 0.0.0.0:8006->8005/tcp   maas



  • 通过 telnet ip+port 看看服务是否正常启动

shd:maas_qa_backend shenhaodong$ telnet 127.0.0.1 8006
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

# 可以看到在容器外可以访问到服务的

3. 构建 nginx 镜像并使用自定义网络启动
  • 构建镜像

shd:nginx shenhaodong$ docker build . -t ngimages

[+] Building 9.3s (2/3)                                                                                                                                                                                          
=> [internal] load build definition from Dockerfile                                                                                                                                                         0.0s
=> => transferring dockerfile: 36B                                                                                                                                                                         0.0s
=> [internal] load .dockerignore                                                                                                                                                                           0.0s
=> => transferring context: 2B                                                                                                                                                                             0.0s
=> [internal] load metadata for docker.io/library/nginx:latest                                                                                                                                             9.2s
-


  • 启动 nginx 容器

(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker run -itd -p8009:8080 --name ng --net shdnet 3893b8f7aa8a
4e969d462c03a1d96e35b2a477abc4ee76285e3416ec6951a9f82b35029a7d4c
(maas_backend_env) shd:maas_qa_backend shenhaodong$
(maas_backend_env) shd:maas_qa_backend shenhaodong$
(maas_backend_env) shd:maas_qa_backend shenhaodong$ docker ps
CONTAINER ID   IMAGE         COMMAND                 CREATED         STATUS         PORTS                                                     NAMES
4e969d462c03   3893b8f7aa8a   "/docker-entrypoint.…"   2 seconds ago   Up 2 seconds   80/tcp, 0.0.0.0:8009->8080/tcp                             ng
dba395715a34   34d6ab3660af   "/entrypoint.sh"         7 minutes ago   Up 7 minutes   9191/tcp, 0.0.0.0:8008->8001/tcp, 0.0.0.0:8006->8005/tcp   maas


  • 使用 curl ip+port 看是否可以访问成功

shd:maas_qa_backend shenhaodong$  curl 127.0.0.1:8009
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Page not found at /</title>
<meta >
<style type="text/css">
  html * { padding:0; margin:0; }
  body * { padding:10px 20px; }
  body * * { padding:0; }
  body { font:small sans-serif; background:#eee; color:#000; }
  body>div { border-bottom:1px solid #ddd; }
  h1 { font-weight:normal; margin-bottom:.4em; }
  h1 span { font-size:60%; color:#666; font-weight:normal; }
  table { border:none; border-collapse: collapse; width:100%; }
  td, th { vertical-align:top; padding:2px 3px; }
  th { width:12em; text-align:right; color:#666; padding-right:.5em; }
  #info { background:#f6f6f6; }
  #info ol { margin: 0.5em 4em; }
  #info ol li { font-family: monospace; }
  #summary { background: #ffc; }
  #explanation { background:#eee; border-bottom: 0px none; }
</style>
</head>
<body>
<div>
  <h1>Page not found <span>(404)</span></h1>
  <table>
    <tr>
      <th>Request Method:</th>
      <td>GET</td>
    </tr>
    <tr>
      <th>Request URL:</th>
      <td>http://127.0.0.1:8009/</td>
    </tr>
     
  </table>
</div>
<div>
   
    <p>
    Using the URLconf defined in <code>maas_qa_backend.urls</code>,
    Django tried these URL patterns, in this order:
    </p>
    <ol>
       
        <li>
           
              admin/
               
           
        </li>
       
        <li>
           
              ^swagger(?P<format>\.json|\.yaml)$
              [name='schema-json']
           
        </li>
       
        <li>
           
              swagger/
              [name='schema-swagger-ui']
           
        </li>
       
        <li>
           
              redoc/
              [name='schema-redoc']
           
        </li>
       
        <li>
           
              api/common/select/detail
               
           
        </li>
       
        <li>
           
              api/users/
               
           
        </li>
       
        <li>
           
              api/productlines/
               
           
        </li>
       
        <li>
           
              api/project/
               
           
        </li>
       
        <li>
           
              api/projects/
               
           
        </li>
       
        <li>
           
              api/home/
               
           
        </li>
       
    </ol>
    <p>
       
      The empty path didn't match any of these.
    </p>
   
</div>

<div>
  <p>
    You're seeing this error because you have <code>DEBUG = True</code> in
    your Django settings file. Change that to <code>False</code>, and Django
    will display a standard 404 page.
  </p>
</div>
</body>
</html>


over

posted @ 2024-03-06 15:15  游走De提莫  阅读(119)  评论(0编辑  收藏  举报