Dockerising Flutter Web app with dockerised Flutter build and Nginx
Flutter Web app build and host with Docker containers
Several examples of Dockerfiles for building and hosting Flutter web apps, Ubuntu-based Flutter Build image + Webapp image on Nginx.

All-in-one Dockerfile
Typical Dockerfile for building Flutter webapps might look like the one blow. It uses ubuntu:latest as a base build image, installs Flutter, builds the webapp, and copies it to the nginx:alpine image. The resulting image of the hosted on nginx webapp would be a bit more then 73 MB, thanks to nginx:alpine’s size of 48.2MB.
FROM ubuntu:latest AS builder # Install dependencies RUN apt-get update && apt-get install -y \ curl \ git \ unzip \ xz-utils \ zip \ libglu1-mesa # Install Flutter RUN git clone https://github.com/flutter/flutter.git /flutter ENV PATH="/flutter/bin:${PATH}" RUN flutter doctor RUN flutter channel stable RUN flutter upgrade # Add build argument ARG MY_MEGA_API_URL ENV MY_MEGA_API_URL=${MY_MEGA_API_URL} # Copy app source WORKDIR /app COPY . . # Get app dependencies RUN flutter pub get # Clean any existing builds and build for web RUN flutter clean RUN flutter build web --release --verbose --dart-define=MY_MEGA_API_URL=${MY_MEGA_API_URL} # Stage 2 - Create the final image with nginx to serve the static files FROM nginx:alpine # Copy the build from the builder stage COPY --from=builder /app/build/web /usr/share/nginx/html # Copy nginx configuration RUN echo 'server { \ listen 80; \ server_name localhost; \ root /usr/share/nginx/html; \ index index.html; \ \ # Handle static assets with proper MIME types \ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|json)$ { \ expires 1y; \ add_header Cache-Control "public, immutable"; \ try_files $uri =404; \ } \ \ # Handle Flutter web routing \ location / { \ try_files $uri $uri/ @fallback; \ } \ \ location @fallback { \ rewrite ^.*$ /index.html last; \ } \ \ # Security headers \ add_header X-Frame-Options "SAMEORIGIN" always; \ add_header X-Content-Type-Options "nosniff" always; \ add_header X-XSS-Protection "1; mode=block" always; \ }' > /etc/nginx/conf.d/default.conf # Expose port EXPOSE 80 # Start Nginx CMD ["nginx", "-g", "daemon off;"] Dockerised Flutter
But if you have several Flutter web apps you are working on those temborary files for intermediate build image would eat up some of your disk space. It makes sense to create a single image for flutter build and reuse it across the projects. Here the one below takes 3.47GB on my PC only once.
Here is a simple Dockerfile for Flutter build image. Save it as a Dockerfile.flutter.
FROM ubuntu:latest AS builder # Install dependencies RUN apt-get update && apt-get install -y \ curl \ git \ unzip \ xz-utils \ zip \ libglu1-mesa # Install Flutter RUN git clone https://github.com/flutter/flutter.git /flutter ENV PATH="/flutter/bin:${PATH}" RUN flutter doctor RUN flutter channel stable RUN flutter upgrade Let’s build it with
docker build -f Dockerfile.flutter -t rg-flutter:1.0 . Flutter Web App Simplified Dockerfile
FROM rg-flutter:1.0 AS builder # Add build argument ARG MY_MEGA_API_URL ENV MY_MEGA_API_URL=${MY_MEGA_API_URL} # Copy app source WORKDIR /app COPY . . # Get app dependencies RUN flutter pub get # Clean any existing builds and build for web RUN flutter clean RUN flutter build web --release --verbose --dart-define=MY_MEGA_API_URL=${MY_MEGA_API_URL} # Stage 2 - Create the final image with nginx to serve the static files FROM nginx:alpine # Copy the build from the builder stage COPY --from=builder /app/build/web /usr/share/nginx/html # Copy nginx configuration RUN echo 'server { \ listen 80; \ server_name localhost; \ root /usr/share/nginx/html; \ index index.html; \ \ # Handle static assets with proper MIME types \ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|json)$ { \ expires 1y; \ add_header Cache-Control "public, immutable"; \ try_files $uri =404; \ } \ \ # Handle Flutter web routing \ location / { \ try_files $uri $uri/ @fallback; \ } \ \ location @fallback { \ rewrite ^.*$ /index.html last; \ } \ \ # Security headers \ add_header X-Frame-Options "SAMEORIGIN" always; \ add_header X-Content-Type-Options "nosniff" always; \ add_header X-XSS-Protection "1; mode=block" always; \ }' > /etc/nginx/conf.d/default.conf # Expose port EXPOSE 80 # Start Nginx CMD ["nginx", "-g", "daemon off;"]