Do I need to set up a different Fly app for my Fusionauth, or does docker-compose.yml take care of it?

Howdy.

I’ve been using the Remix Blues stack to build my app. Part of that is using the FusionAuth community edition to handle authentication - which I’ve got running in my localhost docker on port 9011.

So, I have my main app running on localhost:3000, and that I CAN get to deploy (https://yala-deploy.fly.dev), but I don’t seem to be able to get the authorization working.

In my local dev environment, I’m using docker-compose to launch the community edition of fusionauth (and it’s required elasticsearch) to login and such; I’m wondering if that’s not possible here, if I should either launch a second app to host my fusionauth community instance, OR find a different auth solution entirely (Firebase? AWS?) that will require quite a bit of recoding.

My source code is at GitHub - kerryboyko/YetAnotherLinkAggregator: Yet another link aggregator. A reddit clone, just to see if I really could create "reddit from scratch" with NodeJS and react. Really just a side-project to keep my skills sharp while looking for a job. Built on the Remix Blues stack. and I’m deploying branch ‘main’

Do FusionAuth and your main app need to be on the same host? If you can configure your app to talk to FusionAuth on an arbitrary hostname (e.g. foo.internal:9000) it looks like you could have your app as one process and fusionauth as another process, within a process group. Then you can refer to FusionAuth with an internal network name.

I haven’t tried this, so please let me know if it looks like it can work.

  • Daniel

I’m not quite sure how to do this.

Right now on my local machine, I have a docker-compose file

version: "3"

services:
  db:
    image: postgres:latest
    environment:
      PGDATA: /var/lib/postgresql/data/pgdata
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    networks:
      - db_net
    restart: unless-stopped
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  search:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    environment:
      cluster.name: fusionauth
      bootstrap.memory_lock: "true"
      discovery.type: single-node
      ES_JAVA_OPTS: ${ES_JAVA_OPTS}
    healthcheck:
      test:
        [
          "CMD",
          "curl",
          "--fail",
          "--write-out",
          "'HTTP %{http_code}'",
          "--silent",
          "--output",
          "/dev/null",
          "http://localhost:9200/",
        ]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - search_net
    restart: unless-stopped
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - search_data:/usr/share/elasticsearch/data

  fusionauth:
    image: fusionauth/fusionauth-app:latest
    depends_on:
      db:
        condition: service_healthy
      search:
        condition: service_healthy
    environment:
      DATABASE_URL: jdbc:postgresql://db:5432/fusionauth
      DATABASE_ROOT_USERNAME: ${POSTGRES_USER}
      DATABASE_ROOT_PASSWORD: ${POSTGRES_PASSWORD}
      DATABASE_USERNAME: ${FUSIONAUTH_DATABASE_USERNAME}
      DATABASE_PASSWORD: ${FUSIONAUTH_DATABASE_PASSWORD}
      FUSIONAUTH_APP_MEMORY: ${FUSIONAUTH_APP_MEMORY}
      FUSIONAUTH_APP_RUNTIME_MODE: development
      FUSIONAUTH_APP_URL: http://fusionauth:9011
      SEARCH_SERVERS: http://search:9200
      SEARCH_TYPE: elasticsearch

    networks:
      - db_net
      - search_net
    restart: unless-stopped
    ports:
      - 9011:9011
    volumes:
      - fusionauth_config:/usr/local/fusionauth/config
    extra_hosts:
      - "host.docker.internal:host-gateway"

networks:
  db_net:
    driver: bridge
  search_net:
    driver: bridge

volumes:
  db_data:
  fusionauth_config:
  search_data:

and a dockerfile for my main app:

# base node image
FROM node:16-bullseye-slim as base

# set for base and all layer that inherit from it
ENV NODE_ENV production

# Install openssl for Prisma
RUN apt-get update && apt-get install -y openssl

# Install all node_modules, including dev dependencies
FROM base as deps

WORKDIR /myapp

ADD package.json package-lock.json .npmrc ./
RUN npm install --include=dev

# Setup production node_modules
FROM base as production-deps

WORKDIR /myapp

COPY --from=deps /myapp/node_modules /myapp/node_modules
ADD package.json package-lock.json .npmrc ./
RUN npm prune --omit=dev

# Build the app
FROM base as build

WORKDIR /myapp

COPY --from=deps /myapp/node_modules /myapp/node_modules

ADD prisma .
RUN npx prisma generate

ADD . .
RUN npm run build

# Finally, build the production image with minimal footprint
FROM base

WORKDIR /myapp

COPY --from=production-deps /myapp/node_modules /myapp/node_modules
COPY --from=build /myapp/node_modules/.prisma /myapp/node_modules/.prisma

COPY --from=build /myapp/build /myapp/build
COPY --from=build /myapp/public /myapp/public
ADD . .

CMD ["npm", "start"]

And here’s my fly.toml:

# fly.toml app configuration file generated for yalalinksite on 2023-07-18T09:55:47-04:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = "yala-deploy"
primary_region = "atl"
kill_signal = "SIGINT"
kill_timeout = "5s"

[experimental]
  auto_rollback = true

[deploy]
  release_command = "bash ./scripts/migrate.sh"

[env]
  PORT = "3000"

  IMGUR_AUTH_URL="https://api.imgur.com/oauth2/authorize"
  IMGUR_ACCESS_TOKEN_URL="https://api.imgur.com/oauth2/token"
  IMGUR_ACCESS_UPLOAD_URL="https://api.imgur.com/3/image"

[[services]]
  protocol = "tcp"
  internal_port = 3000
  processes = ["app"]

  [[services.ports]]
    port = 80
    handlers = ["http"]
    force_https = true

  [[services.ports]]
    port = 443
    handlers = ["tls", "http"]
  [services.concurrency]
    type = "connections"
    hard_limit = 25
    soft_limit = 20

  [[services.tcp_checks]]
    interval = "15s"
    timeout = "2s"
    grace_period = "1s"
    restart_limit = 0

  [[services.http_checks]]
    interval = "10s"
    timeout = "2s"
    grace_period = "5s"
    restart_limit = 0
    method = "get"
    path = "/healthcheck"
    protocol = "http"

[metrics]
  port = 8081
  path = "/metrics"

Thanks for the extra detail - docker compose files are not directly supported (as in, you can’t automatically tell Fly.io “just deploy what my docker-compose.yaml is declaring”). You would have to deploy each service (postgres, elasticsearch, fusionauth and your own application as separate Fly.io apps and make them talk to each other via internal names. Apps within an organization can easily talk to each other using private networking/names.

The thing I mentioned about process groups probably doesn’t apply here directly because for process groups, everything would need to exist in a single image/app, which is not the case for you.

Keep in mind Fly.io does have a Postgres service, you can leverage that instead of having to stand up your own Postgres from a dockerfile.

  • Daniel

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.