背景
最近在和组内小伙伴一起写接口测试平台后端,使用的是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 name="robots" content="NONE,NOARCHIVE">
<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 id="summary">
<h1>Page not found <span>(404)</span></h1>
<table class="meta">
<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 id="info">
<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 id="explanation">
<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>
网友评论