1

I'm trying to build a dart server that can serve flutter web apps. I've tried it a few different ways, building from scratch, using shelf (and shelf_static), and lastly GetX, but I can't get them to run in a docker container. For instance, I currently have a simple structure:

-myApp/
  -web/
  -Dockerfile
  -pubspec.yaml
  -server.dart

I took the basic flutter demo app (with the floating button & counter), added web support, then did $ flutter build web, and took the build/web folder and copied it here as just web. Pubspec only includes get_server and build_runner, the server.dart file is only:

import 'package:get_server/get_server.dart';
void main() => runApp(GetServer(home: FolderWidget('web')));

And then my Dockerfile looks like this (based on this github repo):

################
FROM google/dart:2.10

RUN apt -y update && apt -y upgrade

WORKDIR /app
COPY pubspec.yaml /app/pubspec.yaml
RUN dart pub get
COPY . .
RUN dart pub get --offline

RUN dart pub run build_runner build --delete-conflicting-outputs
RUN dart compile exe /app/server.dart -o /app/server

########################
FROM subfuzion/dart:slim
COPY --from=0 /app /app
EXPOSE 8080
ENTRYPOINT ["/app/server"]

If I run the server from the command line:

$ dart server.dart

It runs perfectly. But if I build docker and run it:

$ docker build -t myApp .
$ docker run -d -p 8080:8080 myapp

It just says that the page can't be found. Does anyone know what I'm doing wrong? Or have suggestions for how to host a Flutter Web App using a Dart Server (it doesn't have to be GetX).

1 Answer 1

2

I'm going to update this because this is my only post that gets any traffic. The first answer was that I'm an idiot trying to serve the website from the same directory on my computer as in my docker container (suprise! that didn't work). Secondly, I've created some automation scripts that speeds this process and allows it to be easily pushed to Google's CloudRun in case anyone is interested. I'm also going to change to showing a Shelf server, since this seems to be the default now.

My full directory setup for my Flutter project is just this:

directory_to_flutter_project/
simple_server/
scripts/

Inside simple_server I have a dart project with 2 folders, bin and web. bin contains only server.dart:

import 'package:functions_framework/serve.dart';
import 'package:shelf_static/shelf_static.dart';

Future<void> main(List<String> args) async {
  await serve(args, _nameToFunctionTarget);
}

FunctionTarget? _nameToFunctionTarget(String name) {
  switch (name) {
    case 'function':
      return FunctionTarget.http(
        createStaticHandler('app/web', defaultDocument: 'index.html'),
      );
    default:
      return null;
  }
}

The web directory is where we're going to build our Flutter PWA. You may want to include a redirect.html file in it if you need any kind of authorization.

Then, when you're ready, you can create a bash script like so (I put this in the scripts directory):

#!/bin/bash

projectId="gcp-project-id"
projectName="gcp-project-name"
version="3"

# only needed the first time
gcloud config set project $projectId
gcloud auth login

# change to primary app directory & build flutter web & go back to main level

cd directory_to_flutter_project && flutter build web && cd ..

# if you're having issues with rendering, which we were, you can try the following instead
cd directory_to_flutter_project && flutter build web --web-renderer canvaskit --release && cd ..

# clear web directory from server
rm simple_server/web -r

# copy the built web folder to the server directory
cp directory_to_flutter_project/build/web simple_server/web -r

# change to the server directory
cd simple_server &&

# Create docker container
docker build -t $projectName .

#
# The rest is for pushing to GCP
#

#push it to GCP Cloud Repository
docker build -t gcr.io/$projectId/$projectName:v$version .
docker push gcr.io/$projectId/$projectName:v$version

# return back to root directory
cd ..

# deploy on google cloud
gcloud run deploy $projectName --image gcr.io/$projectId/$projectName:v$version
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.