dockernginxdockerfileazure-aksnginx-config

404 not found nginx/1.27.0 while running a docker image for React web application


We have React web app. We created a docker file and it was working fine. When running docker image we were able to successfully deploy and run our application.

But we're facing one issue. Whenever we're navigating from localhost everything is working fine as expected. When we route to other page and the url gets updated to http://localhost:32768/admin/tenants and when reload at this point it's not working and getting this error. enter image description here

This error occurs only when we reload the page, as it wasn't able to identify the host. We explored online and created this custom-nginx.conf file

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    error_page   500 502 503 504  /50x.html;

    location / { }

    location ~^/test/ {
        alias /usr/share/nginx/public;
    }

    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

This is the place in our docker file where we're serving using nginx.

# Stage 2: Serve the application with Nginx
FROM nginx:alpine

# Copy the custom Nginx configuration file
COPY custom-nginx.conf /etc/nginx/conf.d/default.conf

# Copy the built application from the previous stage
COPY --from=build /app/react-app/dist /usr/share/nginx/html

# Expose the port the app runs on
EXPOSE 80

# Start Nginx server
CMD ["nginx", "-g", "daemon off;"]

Could anyone help us what we're missing. We're experience the same issue when deploying the react webapp using Azure Kubernetes service.

The application was working fine only when reloading or the directly navigating if the url is appended with additional parameters.


Solution

  • The issue with your Nginx configuration for a React application running in a Docker container occurs when navigating directly to a route (like /admin/tenants).

    To resolve the issue you need to adjust your Nginx configuration to handle client-side routing by adding the following to the Nginx configuration:

    location / {
      try_files $uri /index.html;
    }
    
    

    All routes are served by index.html, allowing React Router to manage them on the client side.

    server {
        listen       80;
        server_name  localhost;
    
        root   /usr/share/nginx/html;
        index  index.html;
    
        location / {
            try_files $uri /index.html;
        }
        location /static/ {
            alias /usr/share/nginx/html/static/;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    
    

    I refered this DOC to use React Router in React apps.

    import React from 'react';
    import { BrowserRouter as Router, Routes, Route, Link, Outlet, useParams } from 'react-router-dom';
    const BlogPosts = {
      'first-blog-post': {
        title: 'First Blog Post',
        description: 'Lorem ipsum dolor sit amet, consectetur adip.'
      },
      'second-blog-post': {
        title: 'Second Blog Post',
        description: 'Hello React Router v6'
      }
    };
    function Home() {
      return (
        <div style={{ padding: 20 }}>
          <h2>Home View</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adip.</p>
        </div>
      );
    }
    function About() {
      return (
        <div style={{ padding: 20 }}>
          <h2>About View</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adip.</p>
        </div>
      );
    }
    function NoMatch() {
      return (
        <div style={{ padding: 20 }}>
          <h2>404: Page Not Found</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adip.</p>
        </div>
      );
    }
    function Posts() {
      return (
        <div style={{ padding: 20 }}>
          <h2>Blog</h2>
          <Outlet />
        </div>
      );
    }
    function PostLists() {
      return (
        <ul>
          {Object.entries(BlogPosts).map(([slug, { title }]) => (
            <li key={slug}>
              <Link to={`/posts/${slug}`}>
                <h3>{title}</h3>
              </Link>
            </li>
          ))}
        </ul>
      );
    }
    function PostDetail({ post }) {
      return (
        <div>
          <h2>{post.title}</h2>
          <p>{post.description}</p>
        </div>
      );
    }
    function App() {
      return (
        <Router>
          <nav style={{ margin: 10 }}>
            <Link to="/" style={{ padding: 5 }}>Home</Link>
            <Link to="/posts" style={{ padding: 5 }}>Posts</Link>
            <Link to="/about" style={{ padding: 5 }}>About</Link>
          </nav>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/posts" element={<Posts />}>
              <Route index element={<PostLists />} />
              <Route path=":slug" element={<PostDetailWrapper />} />
            </Route>
            <Route path="*" element={<NoMatch />} />
          </Routes>
        </Router>
      );
    }
    function PostDetailWrapper() {
      const { slug } = useParams();
      const post = BlogPosts[slug];
    
      if (!post) {
        return <NoMatch />;
      }
    
      return <PostDetail post={post} />;
    }
    export default App;
    
    

    enter image description here

    enter image description here

    I used this link to deploy a Web App to Azure Kubernetes Service with Docker

    enter image description here