在一个Dockerfile中Dockerize next.js和nginx



我已经使用两个docker镜像成功地对我的应用程序进行了docker镜像,一个用于nginx,另一个用于应用程序,它运行良好,因为我使用了docker compose。现在我只想有一个包含应用程序和nginx的Dockerfile,然后在我的本地计算机上运行它。我怎么能做到这一点?

这是我的nginx/default.conf

# Cache zone
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;
upstream nextjs {
server nextjs:3000;
}
server {
listen 80 default_server;
server_name _;
server_tokens off;
gzip on;
gzip_proxied any;
gzip_comp_level 4;
gzip_types text/css application/javascript image/svg+xml;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# BUILT ASSETS (E.G. JS BUNDLES)
# Browser cache - max cache headers from Next.js as build id in url
# Server cache - valid forever (cleared after cache "inactive" period)
location /_next/static {
proxy_cache STATIC;
proxy_pass http://nextjs;
}
# STATIC ASSETS (E.G. IMAGES)
# Browser cache - "no-cache" headers from Next.js as no build id in url
# Server cache - refresh regularly in case of changes
location /static {
proxy_cache STATIC;
proxy_ignore_headers Cache-Control;
proxy_cache_valid 60m;
proxy_pass http://nextjs;
}
# DYNAMIC ASSETS - NO CACHE
location / {
proxy_pass http://nextjs;
}
}

My/nginx/Dockerfile

FROM nginx:alpine as build
RUN rm /etc/nginx/conf.d/*
COPY ./default.conf /etc/nginx/conf.d/
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]

/Dockerfile[旧]

FROM node:alpine
WORKDIR /usr/app
RUN npm install --global pm2
COPY ./package*.json ./
RUN npm install --production
COPY ./ ./
RUN npm run build
EXPOSE 3000
USER node
CMD [ "pm2-runtime", "start", "npm", "--", "start" ]

这是新的Dockerfile

FROM node:alpine
WORKDIR /usr/app
RUN npm install --global pm2
COPY ./package*.json ./
RUN npm install --production
COPY ./ ./
# Build app
RUN npm run build
EXPOSE 3000
USER node
CMD [ "pm2-runtime", "start", "npm", "--", "start" ]
FROM nginx:stable-alpine
COPY --from=build /usr/app/.next /usr/share/nginx/html
RUN mkdir /usr/share/nginx/log
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/default.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

我可以构建它,但每当我运行映像时都会抛出错误在上游未找到主机";nextjs:3000";在/etc/nginx/conf.d/default.conf:5

感谢@八角形我终于通过更改nginx/default.conf 解决了这个问题

我的Dockerfile

# build react app, it should be /build
# FROM node:12.2.0-alpine as build
FROM node:13-alpine as build
WORKDIR /app
COPY package.json /app/package.json
RUN npm install --only=prod
COPY . /app
RUN npm run build
# Creating nginx image and copy build folder from above
# FROM nginx:1.16.0-alpine
FROM nginx:stable-alpine
RUN mkdir /usr/share/nginx/buffer
COPY --from=build /app/.next /usr/share/nginx/buffer
COPY --from=build /app/deploy.sh /usr/share/nginx/buffer
RUN chmod +x /usr/share/nginx/buffer/deploy.sh
RUN cd /usr/share/nginx/buffer && ./deploy.sh
RUN mkdir /usr/share/nginx/log
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

和nginx/default.conf

server {
listen 80;
location / {
root   /usr/share/nginx/html/pages;
index  index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page   500 502 503 504  /50x.html;
location = /50x.html {
root   /usr/share/nginx/html/pages;
}
error_log /usr/share/nginx/log/error.log warn;
access_log /usr/share/nginx/log/access.log;
}

之所以得到host not found in upstream "nextjs:3000" in /etc/nginx/conf.d/default.conf:5,是因为根据您的nginx/default.conf,nginx会将所有收到的请求转发到http://nextjs。这以前是有效的,因为您可能在一个名为nextjs的单独容器中运行了节点。现在您尝试在同一个容器中运行nginx和node,因此nextjs容器不再存在,nginx没有任何可转发请求的内容。

在我看来,您试图在同一个容器中运行反向代理和节点应用程序,而在两个单独的容器中运行它们应该更可取,就像以前一样。

如果你只是在本地开发你的节点应用程序,你不需要nginx反向代理,你可以直接向节点应用程序发送请求,所以只需要节点容器。当您部署到生产环境中时,通常会出于各种原因使用nginx反向代理,如SSL终止和负载平衡。在这种情况下,您可以将nginx和node容器一起部署。

如果您真的想继续使用当前的方法,那么您可能必须将请求转发到http://localhost而不是http://nextjs,尽管我认为这不是唯一的问题。节点可能也没有在您的容器中运行。在多阶段docker构建中使用CMD [ "pm2-runtime", "start", "npm", "--", "start" ]启动Node应用程序,该节点映像将被丢弃。您将不得不在nginx容器中启动Node应用程序。

最新更新