Basemap fails to render inside Docker container, works otherwise

634
1
Jump to solution
05-23-2022 10:21 AM
GeoSolver
New Contributor III

I'm attempting to deploy a simple web app built with ArcGIS Javascript API v4.23.  It's a React app that displays a single Map within a single MapView.

The problem I'm having is that the basemap tiles don't render when the app is deployed as a Docker container.  Has anyone else seen this?

I can launch the app via localhost:3000 and everything works as expected.  The map renders within the correct div and it shows the gray canvas basemap tiles.  The CSS is also loading correctly and the zoom +/- buttons render correctly.  All of this correct behavior happens when the app is launched locally.  I can deploy it IIS or I can just run 'npm start' in VS Code and it runs without issues.  This is how it displays:

react-arcgis-localhost.JPG

Code within the React app that creates the map and map view:

 

import logo from './logo.svg';
import './App.css';
import { useEffect, useState, useRef } from "react";
import esriConfig from "@arcgis/core/config";
import Map from "@arcgis/core/Map";
import MapView from "@arcgis/core/views/MapView";
import FeatureLayer from "@arcgis/core/layers/FeatureLayer";

function App() {
  const mapRef = useRef();

  esriConfig.apiKey =
  "removed";

  const initMap = () => {
    const map = new Map({
      basemap: "arcgis-light-gray",
      layers: []
    });
  
    const view = new MapView({
      map: map,
      center: [-82.354, 27.895],
      zoom: 9,
      container: mapRef.current,
    });
  };

  useEffect(() => {
    initMap();
  }, []);

  return (
    <div className="App">
      <div id="map-div" ref={mapRef}>
        
      </div>
    </div>
  );
}

export default App;

 

 

All of the above works when hosted locally or build and deployed to IIS.

But the ultimate goal is to deploy this app within a Docker container.  The image builds successfully and also runs successfully, but when I browse the app running inside the container the basemap tiles don't render.

react-arcgis-docker.JPG

I get the same result in Chrome and Edge.  There are no errors or exception thrown in the browser's console.  It's as if the JS API is loading successfully but somehow the image tiles aren't rendering and I can't see any reason why this would fail only inside a Docker container.

Dockerfile

 

FROM node:latest as build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM nginx:latest

COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/build/ /usr/share/nginx/html/

 

 

.dockerignore file

 

node_modules
Dockerfile
.git

 

 

default.conf for NGINX

 

server {
    listen 80;
    listen [::]:80;

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

    server_name localhost;

    location / {
        try_files $uri $uri/ =404;
    }
}

 

 

I believe the problem has to have something to do with NGINX and how it is failing to handle the image tiles correctly, but that's just a half-baked theory.

Update...

I noticed some differences in the requests being made by each version of this app.  In the network tab of Chrome's developer tools it looks like the app makes an extra call when running locally that is not made when it's running in a docker container.

Locally it makes two calls to LightGray:Base and LightGray:Labels, and also World_Basemap_v2 further down.

react-arcgis-local-network-tab.JPG

I see fewer calls for the light gray basemap resource in the Docker container and no request for World_Basemap_v2 at all.

react-arcgis-docker-network-tab.JPG

 

Any help is appreciated.  Thanks.

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
GeoSolver
New Contributor III

I found two work-arounds.

The problem seems to be with the esriConfig module, specifically defining an API key within a React app. A key is required to use the premium set of basemaps which includes the one I'm using, "arcgis-light-gray". I have always defined my developer API key in my ArcGIS JS apps and I've done so in this React app as well. But this module appears to be broken in React. Either that or I need to reference the module differently than I currently am. If so, it's not covered in any documentation I could find.

Work-around #1 - use a non-premium basemap like "gray" or "gray-vector". These basemaps lack the same level of detail at higher zoom levels, making this approach unacceptable if you want to zoom in to larger scales and see detail on individual parcels.

Work-around #2 - uninstall @arcgis/core and install esri-loader instead. This set of modules appears to be the better way to use the ArcGIS JS API in React. With esri-loader the modules are imported with the loadModules function instead of require or import. After refactoring the app to use esri-loader I am now able to define my API key and the premium "arcgis-light-gray" basemap renders correctly.

import logo from "./logo.svg";
import "./App.css";
import { loadModules } from "esri-loader";

function App() {

  loadModules(['esri/config', 'esri/views/MapView', 'esri/Map']).then(([esriConfig, MapView, Map]) => {
    esriConfig.apiKey = "REMOVED";
    
    const map = new Map({
      basemap: 'arcgis-light-gray'
    });

    const mapView = new MapView({
      map: map,
      zoom: 10,
      center: [-82.5, 28],
      container: "map-div"
    });
  });

  return (
    <div className="App">
      <div id="map-div"></div>
    </div>
  );
}

export default App;

View solution in original post

0 Kudos
1 Reply
GeoSolver
New Contributor III

I found two work-arounds.

The problem seems to be with the esriConfig module, specifically defining an API key within a React app. A key is required to use the premium set of basemaps which includes the one I'm using, "arcgis-light-gray". I have always defined my developer API key in my ArcGIS JS apps and I've done so in this React app as well. But this module appears to be broken in React. Either that or I need to reference the module differently than I currently am. If so, it's not covered in any documentation I could find.

Work-around #1 - use a non-premium basemap like "gray" or "gray-vector". These basemaps lack the same level of detail at higher zoom levels, making this approach unacceptable if you want to zoom in to larger scales and see detail on individual parcels.

Work-around #2 - uninstall @arcgis/core and install esri-loader instead. This set of modules appears to be the better way to use the ArcGIS JS API in React. With esri-loader the modules are imported with the loadModules function instead of require or import. After refactoring the app to use esri-loader I am now able to define my API key and the premium "arcgis-light-gray" basemap renders correctly.

import logo from "./logo.svg";
import "./App.css";
import { loadModules } from "esri-loader";

function App() {

  loadModules(['esri/config', 'esri/views/MapView', 'esri/Map']).then(([esriConfig, MapView, Map]) => {
    esriConfig.apiKey = "REMOVED";
    
    const map = new Map({
      basemap: 'arcgis-light-gray'
    });

    const mapView = new MapView({
      map: map,
      zoom: 10,
      center: [-82.5, 28],
      container: "map-div"
    });
  });

  return (
    <div className="App">
      <div id="map-div"></div>
    </div>
  );
}

export default App;
0 Kudos