Using Docker Compose for React Storybook Development
So here's the situation. We have a single Docker container for our Gatsby-based project. We have this hooked up to AWS Amplify for CI/CD. It's looking pretty, here's the Dockerfile
# # Create the installation layer FROM node:12.7.0-alpine as install WORKDIR /usr/app # Install Dependencies COPY ./package.json ./package-lock.json ./ RUN npm i --silent # # Create the application development layer FROM node:12.7.0-alpine as develop # Expose Ports EXPOSE 8000 # Create and change into a directory in the container WORKDIR /usr/app COPY --from=install /usr/app/. . COPY . . # # @TODO: Create the testing layer # A container build should fail here if tests fail # RUN npm test or static analysis, linting, whatever # # @TODO: Create the production build layer # This should only result in production npm deps installed FROM node:12.7.0-alpine as production WORKDIR /usr/app # Install prod deps COPY ./package.json ./package-lock.json ./ RUN npm i --production --silent # Copy code from... somewhere COPY . . # Run a gatsby build production RUN npm run build # Should just be static files (HTML, JS, CSS, Media assets) # For later copying # # Create the file serving layer (scratch image) # This should end up with only static files in a file system # With no actual operating system or binaries FROM scratch WORKDIR /build COPY --from=production /usr/app/public . # We now should have a directory called public # With only static files (HTML, JS, CSS, Media assets) # Default Command - This is never used CMD [""]
And here is our Docker Compose file to make it super easy to spin up, tear down, rebuild with a command like
docker-compose up. It's amazing! Wanna do it in the background, throw in a
-d at the end. Need to totally rebuild it? Add a dash of that
--build flag. It's fantastics.
```yml version: "3.7" services: heroines-site: build: context: ./public-site target: develop image: heroines-site container_name: heroines-site init: true command: npm run develop -- -H 0.0.0.0 ports: - 8000:8000 volumes: - /usr/app/node_modules - ./public-site:/usr/app
This is perfect. It does just what we want, creates a pretty slim image for local. AWS Amplify also builds this from a master-commit, and builds it inside a consistent Docker build container. So we're good!
Okay, so, we have a local build of Gatsby running on
localhost:8000/. We get access to the GraphQL endpoint at
localhost:8000/__graphql as well.
What if we wanted to run a parallel container that ran React Storybook? Well that's a different port, and a different concern. We 100% don't want to try to run this in production, but we want that for local development. Trust me, it's very nice.
So we make another container. Consider this a
sidecar container pattern. It looks like this:
version: "3.7" services: heroines-site: build: context: ./public-site target: develop image: heroines-site container_name: heroines-site init: true command: npm run develop -- -H 0.0.0.0 ports: - 8000:8000 volumes: - /usr/app/node_modules - ./public-site:/usr/app heroines-storybook: build: context: ./public-site target: develop image: heroines-storybook container_name: heroines-storybook init: true command: npm run storybook ports: - 6006:6006 volumes: - /usr/app/node_modules - ./public-site:/usr/app
So we have a whole separate container we can bring up, different than the Gatsby container. The command would look like
docker-compose up heroines-storybook and you will get one running container with storybook, exposing only port
If you wanted to bring up the whole stack (2 containers) you would use the same familiar command of
docker-compose up, and as you can guess, if you only want to bring up the Gatsby site, with no storybook, you can use
docker-compose up heroines-site