Dockerize RedwoodJS

It’s using Firebase for the web hosting but the API is on Cloud Run which I think is what you are referring to by Google’s container service.

1 Like

I figured out a Docker Compose setup, will do a full write up soon but in the meantime check out the repo here.

version: "3.9"
services:
  web:
    build:
      context: .
      dockerfile: ./web/Dockerfile
    ports:
      - "8910:8910"
  api:
    build:
      context: .
      dockerfile: ./api/Dockerfile
    ports:
      - "8911:8911"

Edit: Write up can now be found here.

2 Likes

Beautiful stuff @ajcwebdev!

I’m a bit behind my contributions, but I’ll catch up soon. Feel free to send a PR to jeliasson/redwoodjs-docker when the write up is done, or ping me and I’ll do it :slight_smile:

Will do, I’ll also upgrade the project in the repo to the current version, there’s some slight tweaks we’ll need to make to the current Dockerfiles. Nothing major, I think we just need to remove the babel.config.js files since we no longer have Babel config files in the root of the project.

2 Likes

The docker repository has been moved to the RedwoodJS org under redwoodjs/docker.

For those who have a production or experimental Docker setup, please have a look at Community: How does your Dockerfile(s) look like?

1 Like

@jeliasson

The explanations @ GitHub - ajcwebdev/redwood-docker-compose: An example RedwoodJS application with Docker Compose make it difficult to dev because of the [necessary for all but dev] apiUrl of “http://localhost:8911/api” in the redwood.toml file

I’m going to try to add a docker.toml file

1 Like

Hey @ajoslin103

I had a chat with some people in today’s Redwood Office Hours, and @dthyresson mentioned that you can use environment variables in your redwood.toml. Do you think something like this would work?

redwood.toml

[web]
  apiUrl = "${API_ENDPOINT}"

.env.default

API_ENDPOINT=/.redwood/functions

And then on your production side of things, you’ll set the environment variable API_ENDPOINT that points to the production api?

1 Like

That feels more complicated. We already use .toml files (i.e. netlify.tom)

Ii’ve not had time to see what happed when I tried this earlier today

COPY package.json .
COPY docker.toml ./redwood.toml  ## use docker.toml file as our redwood.toml file
COPY yarn.lock .

I haven’t used anything else but redwood.toml, as I don’t need to override the behavior in this file depending on environment, so I guess it boils down to personal preference here. :slight_smile:

@jeliasson Idea for next step to make Docker integration more “official” — could we setup up a docker/ project over here GitHub - redwoodjs/deploy-target-ci: Testing supported RedwoodJS deploy targets using canary packages

?

@jeliasson I’ve PR’d what works for me for (Docker & Dev side-by-side) to redwoodjs/docker

I’ll likely stay in redwoodjs/docker for another round - @thedavid I’ll get here eventually, looks great

2 Likes

@thedavid Absolutely, but it’s a bit early for that imo. I suggest we continue to evaluate the implementations and builds in redwoodjs/docker. We currently only have three implementations, and a fouth one incoming from @ajoslin103.

Path forward;

  1. Make sure CI build work ( Minor changes after repository move - this needs your attention, David :slight_smile: )
  2. Get more community examples (@ajcwebdev etc)
  3. Have a discussion on what ‘offical’ image(s) would look like (Define official Docker images)
  4. Figure out how to make those images as slim as possible, and have them pass initial CI.

After that, or somewhere in between, we can bring in various images to build in redwoodjs/deploy-target-ci - and add dev and more complex setups as you mentioned.

Thoughts on this path?

3 Likes

Couple things I’d add:

  1. Get a review/feedback from the Fly.io team. They’re wizards with Docker and can help us think through making this robust as well as what doesn’t matter
  2. How can we promote this during Launch Week? We can mark it as Experimental/Preview/Whatever… but we should get the work out.

Well done, everyone. This is just great!!

Hey everyone, I’ve been setting up Docker with Yarn 3 - both api and web in single image. Here’s the final image size (391MB):
Screenshot 2022-05-09 at 1.59.22 PM

Project setup:

  • default Redwood’s test-project (yarn run build:test-project <project directory> from RW Framework Repo)
  • upgraded RW to v1.3.1
  • docker build --platform linux/amd64 .

The major difference from other implementations is in the last two layers. Prisma and Yarn create cache directories in the root which takes quite a bit of size.

I could have deleted these temp directories but in future, there could be some other dependency which may create some different cache directory AND it’s good to have this layer cached in docker for future builds. So, including explicitly what goes in the image (node_modules + other deps) seems a better choice, if there’s some upstream change which requires another dir - build should break, so there’ll be no surprises.

I think a similar implementation should also help Yarn 1 projects.

Here is the Dockerfile: .dockerignore · GitHub

EDIT: Try this! An alternate implementation which is also similar in size is to put these temp files in buildkit cache - got to know by existing fly’s lauch Dockerfile. Maybe even better for consecutive builds: .dockerignore · GitHub

Next steps can be, if there isn’t anything I missed here:

  • PR to redwoodjs/docker
  • Update Dockerfile in fly.io
4 Likes

Great work! :rocket:

I found below particularly interesting. Been trying to get Yarn 3 cache to work myself.

RUN --mount=type=cache,target=/root/.yarn/berry/cache \
    --mount=type=cache,target=/root/.cache yarn install --immutable --inline-builds

I have just updated redwoodjs/docker to version 1.3.1 and I’m looking forward to a PR. Ping me for any input! :wave:t2:

This is my solution

Create docker-compose.yml

# docker-compose.yml
version: "3.9"
services:
  web:
    build:
      context: .
      dockerfile: ./Dockerfile
    image: your_name_image
    ports:
      - "8910:8910"
    env_file:
      - .env
    environment:
      - NODE_ENV=production

Create Dockerfile

# Dockerfile
FROM node:14-alpine as base

WORKDIR /app

COPY package.json package.json
COPY web/package.json web/package.json
COPY api/package.json api/package.json
COPY yarn.lock yarn.lock
RUN yarn install

COPY redwood.toml .
COPY graphql.config.js .

FROM base as web_build

COPY web web
RUN yarn rw build web

FROM base as api_build

COPY api api
RUN yarn rw build api

FROM node:14-alpine

WORKDIR /app

# Only install API packages to keep image small
COPY api/package.json .

RUN yarn install && yarn add react react-dom @redwoodjs/api-server @redwoodjs/internal prisma

COPY graphql.config.js .
COPY redwood.toml .
COPY api api

COPY --from=web_build /app/web/dist /app/web/dist
COPY --from=api_build /app/api/dist /app/api/dist
COPY --from=api_build /app/api/db /app/api/db
COPY --from=api_build /app/node_modules/.prisma /app/node_modules/.prisma

# Entrypoint to @redwoodjs/api-server binary
CMD [ "yarn", "rw-server", "--port", "8910" ]

Remember create .dockerignore

3 Likes

Thanks for this one !!

Would you be willing to add it here?

This is where we are locating the community work until there is an official Docker Deploy

Thanks!

Al;

I think, it that good idea :slight_smile: @ajoslin103

1 Like

any estimate how soon to expect this done?

Let’s organize this effort!

Details here if you’re interested and available: