背景
最近在和組內(nèi)小伙伴一起寫接口測試平臺后端,使用的是drf框架,目前已經(jīng)完成部分工作。在和前端聯(lián)調(diào)試另一個小伙伴使用uwsgi部署起來了撞秋,我感覺這樣部署很low,因為之前有了解過docker所以想著這一次徹底把docker給學(xué)會吧嚣鄙,于是就有了這篇文章吻贿。
首先先看一下我的目錄結(jié)構(gòu)
想法
我計劃使用兩個鏡像來部署我的項目,一個來部署django+uwsgi項目哑子,一個來運(yùn)行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來避免容器停止榨惠,后續(xù)想辦法解決
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
構(gòu)造鏡像,啟動容器
1. 新創(chuàng)建一個網(wǎng)絡(luò)
??因為涉及到兩個容器盛霎,并且容器每次啟動后ip都會變赠橙,所以為了避免這種問題就需要自定義容器網(wǎng)絡(luò)。
容器一共有4種網(wǎng)絡(luò)模式愤炸,host期揪、none、container规个、bridge凤薛,默認(rèn)是bridge模式。因此我們自定義網(wǎng)絡(luò)也最好使用bridge模式诞仓,并且自定義的網(wǎng)絡(luò)可以解決容器啟動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. 構(gòu)建項目鏡像并使用自定義網(wǎng)絡(luò)啟動
因為nginx容器依賴項目的鏡像狂芋,所以需要先啟動項目容器才可以去啟動nginx容器榨馁,具體可以參考nginx的配置文件,
uwsgi_pass maas:8001; #容器名字+端口號
- 構(gòu)建鏡像
(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看看服務(wù)是否正常啟動
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.
# 可以看到在容器外可以訪問到服務(wù)的
3. 構(gòu)建nginx鏡像并使用自定義網(wǎng)絡(luò)啟動
- 構(gòu)建鏡像
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>