VPS上Nginx代理Docker中Laravel应用超时问题求助
问题背景
VPS主机已安装Nginx,通过docker-compose运行Laravel容器(映射主机8000端口到容器80端口),配置Nginx将api.site反向代理到8000端口,但访问API时返回ERR_CONNECTION_TIMED_OUT。主机执行curl 127.0.0.1:8000返回Recv failure: Connection reset by peer,进入容器执行curl 127.0.0.1:80提示无法连接。
核心问题分析
你的Laravel容器运行的是php-fpm服务(监听9000端口),但docker-compose中配置的端口映射是8000:80,而容器内80端口没有任何服务监听,导致外部请求到主机8000端口时,无法和容器内的服务建立连接,最终出现连接重置或超时。
解决方案
方案一:容器内添加Nginx(生产环境推荐)
通过在Laravel容器内安装Nginx,让Nginx监听80端口,并将请求转发到php-fpm(9000端口),这样主机8000端口映射到容器80端口后,就能正常处理HTTP请求。
1. 修改Dockerfile,添加Nginx和Supervisor
更新Dockerfile.prod,安装Nginx、配置站点文件,并用Supervisor管理php-fpm和Nginx进程:
# Versão da imagem Docker PHP ARG PHP_VERSION FROM php:${PHP_VERSION} as php # Seta o Working dir WORKDIR /var/www/app # 安装依赖(添加nginx) RUN apt-get update -y && apt-get install -y --no-install-recommends \ apt-utils \ supervisor \ nginx # 原有依赖安装部分保持不变 RUN apt-get update && apt-get install -y \ zlib1g-dev \ libzip-dev \ unzip \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libpq-dev \ libxml2-dev \ curl \ libcurl4 \ libcurl4-openssl-dev \ nano \ git \ build-essential \ locales \ libicu-dev \ libonig-dev # 原有PHP扩展安装部分保持不变 RUN docker-php-ext-configure gd --with-freetype --with-jpeg RUN docker-php-ext-install -j$(nproc) \ gettext \ gd \ zip \ iconv \ pcntl \ fileinfo \ simplexml \ mysqli \ pdo \ pdo_mysql \ bcmath \ xml \ session # 复制php.ini配置 RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini # 原有Composer安装部分保持不变 RUN cd /tmp \ && curl -sS https://getcomposer.org/installer -o composer-setup.php \ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \ && rm composer-setup.php # 配置Nginx站点 RUN rm /etc/nginx/sites-enabled/default COPY ./docker/nginx/laravel.conf /etc/nginx/sites-available/laravel.conf RUN ln -s /etc/nginx/sites-available/laravel.conf /etc/nginx/sites-enabled/laravel.conf # 配置Supervisor,管理php-fpm和nginx COPY ./docker/supervisord/supervisord.conf /etc/supervisor/conf.d/supervisord.conf # 清理安装缓存 RUN apt-get clean && rm -rf /var/lib/apt/lists/* # 原有用户、权限设置保持不变 RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www COPY . /var/www/app COPY --chown=www:www . /var/www/app USER www # 暴露端口(保持80和9000) EXPOSE 80 9000 # 启动Supervisor CMD ["/usr/bin/supervisord", "-n"]
2. 添加Nginx配置文件
在docker/nginx/laravel.conf中添加以下内容:
server { listen 80; root /var/www/app/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
3. 添加Supervisor配置文件
在docker/supervisord/supervisord.conf中添加:
[supervisord] nodaemon=true [program:php-fpm] command=php-fpm autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:nginx] command=nginx -g "daemon off;" autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0
4. 重启容器
重新构建镜像并启动容器:
docker-compose -f docker-compose.prod.yml up --build -d
方案二:使用Laravel开发服务器(仅测试用,不推荐生产)
临时修改docker-compose配置,让容器运行Laravel自带的serve命令,监听80端口:
services: app.laravel: # 原有配置保持不变 command: php artisan serve --host=0.0.0.0 --port=80
重启容器后,主机执行curl 127.0.0.1:8000即可正常获取Laravel响应,Nginx反向代理也能正常工作。
验证步骤
- 主机执行
curl 127.0.0.1:8000,确认返回Laravel的欢迎页面或API响应 - 访问
http://api.site,确认API请求正常返回
内容的提问来源于stack exchange,提问作者Jean da Silva

