当我的应用程序部署到 Azure 应用程序服务时,为什么我看不到我的 NGINX 日志,但它在本地运行良好?
Why can't I see my NGINX log's when my app is deployed to Azure app services, but it works fine locally?
我有一个 Docker 化的 Django 应用程序,我正在与 Supervisor 协调,这不是最佳选择,但在托管在 Azure 应用程序服务上时需要,因为它们支持 docker- compose 仍处于预览模式(也称为测试版)。
根据最佳实践,我已将 supervisord 中的每个应用程序配置为将日志发送到 STDOUT。当我在本地创建 Docker 图像时它工作正常,运行 它并检查 docker 日志。但是,当我将它部署到 Azure 应用程序服务并检查日志时,我的 Web 应用程序 (Gunicorn) 正在按预期进行记录,但是,来自 NGINX 的日志根本没有出现。
我在我的 Docker 文件中尝试了不同的配置来链接 NGINX 生成的日志文件(例如链接到 /dev/stdout 和 /dev/fd/1)并且我也进入了nginx.conf 配置并尝试直接注销到 /dev/stdout。但无论我做什么,它在本地都运行良好,但在 Azure 上,日志不显示任何 NGINX 日志。我已经粘贴了相关的配置文件,您可以在其中看到带有我尝试过的选项的注释行。希望有人能帮我解决这个问题。
编辑:
我还尝试将 NGINX 应用程序记录到系统中的日志文件中,这在本地也能正常工作,但在 Azure 应用程序服务中却不行。我尝试停用 nginx.conf 中的“user nginx”部分,因为我认为它可能与权限有关,但这也无济于事。
编辑 2:
我还尝试在 Azure 的 Web 应用程序的主目录中创建日志文件,认为这可能与无法在其他目录中创建日志有关——同样,它在本地工作,但 Azure 中的日志是空的.
Docker文件
FROM python:3.8
ENV PYTHONUNBUFFERED 1
###################
# PACKAGE INSTALLS
###################
RUN apt-get update
RUN apt-get install -y pgbouncer
RUN apt-get update && apt-get install -y supervisor
RUN apt-get install nano
RUN apt-get install -y git
RUN apt-get install curl
# Supervisor-stdout for consolidating logs
RUN pip install git+https://github.com/coderanger/supervisor-stdout
###################
# AZURE SSH SETUP
###################
# Install OpenSSH and set the password for root to "Docker!". In this example, "apk add" is the install instruction for an Alpine Linux-based image.
RUN apt-get install -y --no-install-recommends openssh-server \
&& echo "root:Docker!" | chpasswd
# Copy the sshd_config file to the /etc/ssh/ directory
COPY ./bin/staging/sshd_config /etc/ssh/
# Copy and configure the ssh_setup file
RUN mkdir -p /tmp
COPY ./bin/staging/ssh_setup.sh /tmp
RUN chmod +x /tmp/ssh_setup.sh \
&& (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null)
##############
# NGINX SETUP
##############
ENV NGINX_VERSION 1.15.12-1~stretch
ENV NJS_VERSION 1.15.12.0.3.1-1~stretch
RUN set -x \
&& \
NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
found=''; \
for server in \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do \
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
&& dpkgArch="$(dpkg --print-architecture)" \
&& nginxPackages=" \
nginx=${NGINX_VERSION} \
nginx-module-xslt=${NGINX_VERSION} \
nginx-module-geoip=${NGINX_VERSION} \
nginx-module-image-filter=${NGINX_VERSION} \
nginx-module-njs=${NJS_VERSION} \
" \
&& echo "deb https://nginx.org/packages/mainline/debian/ stretch nginx" >> /etc/apt/sources.list.d/nginx.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
$nginxPackages \
gettext-base \
&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list
COPY ./conf/nginx/staging.conf /etc/nginx/conf.d/default.conf
COPY ./conf/nginx/nginx.conf /etc/nginx/nginx.conf
# Linking logs to be able to print errors and logs to STDOUT
#RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
RUN ln -sf /dev/fd/1 /var/log/nginx/access.log && ln -sf /dev/fd/2 /var/log/nginx/error.log
##########################
# DJANGO APPLICATION SETUP
##########################
# install app
RUN mkdir /var/app && chown www-data:www-data /var/app
WORKDIR /var/app
COPY ./requirements.txt /var/app/
RUN pip install -r requirements.txt
COPY . /var/app/
#############
# SUPERVISORD
#############
COPY ./bin/staging/supervisord_main.conf /etc/supervisor/conf.d/supervisord_main.conf
COPY ./bin/staging/prefix-log /usr/local/bin/prefix-log
##########
# VOLUMES
##########
VOLUME /var/logs
########
# PORTS
########
# Expose ports (Added from previous dockerfile)
EXPOSE 80 2222
#########################
# SUPERCRONIC (CRON-TABS)
#########################
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \
SUPERCRONIC=supercronic-linux-amd64 \
SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e
RUN curl -fsSLO "$SUPERCRONIC_URL" \
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
&& chmod +x "$SUPERCRONIC" \
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
#############
# PERMISSIONS
#############
RUN ["chmod", "+x", "/var/app/bin/staging/entrypoint_main.sh"]
RUN ["chmod", "+x", "/usr/local/bin/prefix-log"]
############
# ENTRYPOINT
############
ENTRYPOINT ["/var/app/bin/staging/entrypoint_main.sh"]
supervisord_main.conf
[supervisord]
logfile=/var/logs/supervisord.log ; main log file; default $CWD/supervisord.log
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
loglevel=info ; log level; default info; others: debug,warn,trace
pidfile=/var/logs/supervisord.pid
nodaemon=true ; Run interactivelly instead of deamonizing
# user=www-data
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[inet_http_server]
port = 127.0.0.1:9001
[supervisorctl]
serverurl = http://127.0.0.1:9001
#serverurl=unix:///var/run/supervisor.sock
[program:nginx]
#command=/usr/local/bin/prefix-log /usr/sbin/nginx -g "daemon off;"
command=/usr/sbin/nginx -g "daemon off;"
directory=./projectile/
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
[program:ssh]
command=/usr/local/bin/prefix-log /usr/sbin/sshd -D
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
[program:web]
user=www-data
command=/usr/local/bin/prefix-log gunicorn --bind 0.0.0.0:8000 projectile.wsgi:application # Run each app trough a SH script to prepend logs with the application name
#command=gunicorn --workers=%(ENV_WORKER_COUNT)s --bind 0.0.0.0:8000 myapp_project.wsgi:application
directory=./projectile/
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
nginx.conf
user nginx;
worker_processes 2; # Set to number of CPU cores, 2 cores under Azure plan P1v3
error_log /var/log/nginx/error.log warn;
#error_log /dev/stdout warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/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 /var/log/nginx/access.log main;
#access_log /dev/stdout main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
staging.conf
server {
listen 80 default_server;
error_log /dev/stdout info;
access_log /dev/stdout;
client_max_body_size 100M;
location /static {
root /var/app/ui/build;
}
location /site-static {
root /var;
}
location /media {
root /var;
}
location / {
root /var/app/ui/build; # try react build directory first, if file doesn't exist, route requests to django app
try_files $uri $uri/index.html $uri.html @app;
}
location @app {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto "https"; # assumes https already terminated by the load balancer in front of us
proxy_pass http://127.0.0.1:8000;
proxy_read_timeout 300;
proxy_buffering off;
}
}
解决了。问题是 Azure 应用服务设置了配置设置 WEBSITES_PORT=8000,这使得该应用直接进入 gunicorn 并绕过 NGINX,因此不会创建任何日志。只需删除设置即可解决问题。
我有一个 Docker 化的 Django 应用程序,我正在与 Supervisor 协调,这不是最佳选择,但在托管在 Azure 应用程序服务上时需要,因为它们支持 docker- compose 仍处于预览模式(也称为测试版)。
根据最佳实践,我已将 supervisord 中的每个应用程序配置为将日志发送到 STDOUT。当我在本地创建 Docker 图像时它工作正常,运行 它并检查 docker 日志。但是,当我将它部署到 Azure 应用程序服务并检查日志时,我的 Web 应用程序 (Gunicorn) 正在按预期进行记录,但是,来自 NGINX 的日志根本没有出现。
我在我的 Docker 文件中尝试了不同的配置来链接 NGINX 生成的日志文件(例如链接到 /dev/stdout 和 /dev/fd/1)并且我也进入了nginx.conf 配置并尝试直接注销到 /dev/stdout。但无论我做什么,它在本地都运行良好,但在 Azure 上,日志不显示任何 NGINX 日志。我已经粘贴了相关的配置文件,您可以在其中看到带有我尝试过的选项的注释行。希望有人能帮我解决这个问题。
编辑: 我还尝试将 NGINX 应用程序记录到系统中的日志文件中,这在本地也能正常工作,但在 Azure 应用程序服务中却不行。我尝试停用 nginx.conf 中的“user nginx”部分,因为我认为它可能与权限有关,但这也无济于事。
编辑 2: 我还尝试在 Azure 的 Web 应用程序的主目录中创建日志文件,认为这可能与无法在其他目录中创建日志有关——同样,它在本地工作,但 Azure 中的日志是空的.
Docker文件
FROM python:3.8
ENV PYTHONUNBUFFERED 1
###################
# PACKAGE INSTALLS
###################
RUN apt-get update
RUN apt-get install -y pgbouncer
RUN apt-get update && apt-get install -y supervisor
RUN apt-get install nano
RUN apt-get install -y git
RUN apt-get install curl
# Supervisor-stdout for consolidating logs
RUN pip install git+https://github.com/coderanger/supervisor-stdout
###################
# AZURE SSH SETUP
###################
# Install OpenSSH and set the password for root to "Docker!". In this example, "apk add" is the install instruction for an Alpine Linux-based image.
RUN apt-get install -y --no-install-recommends openssh-server \
&& echo "root:Docker!" | chpasswd
# Copy the sshd_config file to the /etc/ssh/ directory
COPY ./bin/staging/sshd_config /etc/ssh/
# Copy and configure the ssh_setup file
RUN mkdir -p /tmp
COPY ./bin/staging/ssh_setup.sh /tmp
RUN chmod +x /tmp/ssh_setup.sh \
&& (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null)
##############
# NGINX SETUP
##############
ENV NGINX_VERSION 1.15.12-1~stretch
ENV NJS_VERSION 1.15.12.0.3.1-1~stretch
RUN set -x \
&& \
NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
found=''; \
for server in \
hkp://keyserver.ubuntu.com:80 \
hkp://p80.pool.sks-keyservers.net:80 \
pgp.mit.edu \
; do \
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
&& dpkgArch="$(dpkg --print-architecture)" \
&& nginxPackages=" \
nginx=${NGINX_VERSION} \
nginx-module-xslt=${NGINX_VERSION} \
nginx-module-geoip=${NGINX_VERSION} \
nginx-module-image-filter=${NGINX_VERSION} \
nginx-module-njs=${NJS_VERSION} \
" \
&& echo "deb https://nginx.org/packages/mainline/debian/ stretch nginx" >> /etc/apt/sources.list.d/nginx.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
$nginxPackages \
gettext-base \
&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list
COPY ./conf/nginx/staging.conf /etc/nginx/conf.d/default.conf
COPY ./conf/nginx/nginx.conf /etc/nginx/nginx.conf
# Linking logs to be able to print errors and logs to STDOUT
#RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
RUN ln -sf /dev/fd/1 /var/log/nginx/access.log && ln -sf /dev/fd/2 /var/log/nginx/error.log
##########################
# DJANGO APPLICATION SETUP
##########################
# install app
RUN mkdir /var/app && chown www-data:www-data /var/app
WORKDIR /var/app
COPY ./requirements.txt /var/app/
RUN pip install -r requirements.txt
COPY . /var/app/
#############
# SUPERVISORD
#############
COPY ./bin/staging/supervisord_main.conf /etc/supervisor/conf.d/supervisord_main.conf
COPY ./bin/staging/prefix-log /usr/local/bin/prefix-log
##########
# VOLUMES
##########
VOLUME /var/logs
########
# PORTS
########
# Expose ports (Added from previous dockerfile)
EXPOSE 80 2222
#########################
# SUPERCRONIC (CRON-TABS)
#########################
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \
SUPERCRONIC=supercronic-linux-amd64 \
SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e
RUN curl -fsSLO "$SUPERCRONIC_URL" \
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
&& chmod +x "$SUPERCRONIC" \
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
#############
# PERMISSIONS
#############
RUN ["chmod", "+x", "/var/app/bin/staging/entrypoint_main.sh"]
RUN ["chmod", "+x", "/usr/local/bin/prefix-log"]
############
# ENTRYPOINT
############
ENTRYPOINT ["/var/app/bin/staging/entrypoint_main.sh"]
supervisord_main.conf
[supervisord]
logfile=/var/logs/supervisord.log ; main log file; default $CWD/supervisord.log
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
loglevel=info ; log level; default info; others: debug,warn,trace
pidfile=/var/logs/supervisord.pid
nodaemon=true ; Run interactivelly instead of deamonizing
# user=www-data
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[inet_http_server]
port = 127.0.0.1:9001
[supervisorctl]
serverurl = http://127.0.0.1:9001
#serverurl=unix:///var/run/supervisor.sock
[program:nginx]
#command=/usr/local/bin/prefix-log /usr/sbin/nginx -g "daemon off;"
command=/usr/sbin/nginx -g "daemon off;"
directory=./projectile/
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
[program:ssh]
command=/usr/local/bin/prefix-log /usr/sbin/sshd -D
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
[program:web]
user=www-data
command=/usr/local/bin/prefix-log gunicorn --bind 0.0.0.0:8000 projectile.wsgi:application # Run each app trough a SH script to prepend logs with the application name
#command=gunicorn --workers=%(ENV_WORKER_COUNT)s --bind 0.0.0.0:8000 myapp_project.wsgi:application
directory=./projectile/
autostart=true
autorestart=true
stdout_events_enabled=true
stderr_events_enabled=true
stdout_logfile = /dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile = /dev/fd/2
stderr_logfile_maxbytes=0
nginx.conf
user nginx;
worker_processes 2; # Set to number of CPU cores, 2 cores under Azure plan P1v3
error_log /var/log/nginx/error.log warn;
#error_log /dev/stdout warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/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 /var/log/nginx/access.log main;
#access_log /dev/stdout main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
staging.conf
server {
listen 80 default_server;
error_log /dev/stdout info;
access_log /dev/stdout;
client_max_body_size 100M;
location /static {
root /var/app/ui/build;
}
location /site-static {
root /var;
}
location /media {
root /var;
}
location / {
root /var/app/ui/build; # try react build directory first, if file doesn't exist, route requests to django app
try_files $uri $uri/index.html $uri.html @app;
}
location @app {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto "https"; # assumes https already terminated by the load balancer in front of us
proxy_pass http://127.0.0.1:8000;
proxy_read_timeout 300;
proxy_buffering off;
}
}
解决了。问题是 Azure 应用服务设置了配置设置 WEBSITES_PORT=8000,这使得该应用直接进入 gunicorn 并绕过 NGINX,因此不会创建任何日志。只需删除设置即可解决问题。