Skip to content

Instantly share code, notes, and snippets.

@timm-oh
Last active November 3, 2022 14:15
Show Gist options
  • Save timm-oh/ae650ab4b606ad5246e5a6080717c1a7 to your computer and use it in GitHub Desktop.
Save timm-oh/ae650ab4b606ad5246e5a6080717c1a7 to your computer and use it in GitHub Desktop.
Docker / esbuild combination
#!/usr/bin/env node
import esbuild from "esbuild"
import chokidar from "chokidar"
import http from "http"
const watch = process.argv.includes("--watch")
const minify = process.argv.includes("--minify")
const config = {
entryPoints: ["app/assets/javascript/application.js"],
bundle: true,
outdir: "app/assets/builds",
watch: watch,
minify: minify,
sourcemap: true
}
const watchDirectories = [
"./app/assets/builds/*",
"./app/views/**/*.erb",
"./app/helpers/**/*.rb",
]
const port = process.env.LIVE_RELOAD_PORT || 8082
const clients = []
if (watch) {
(async () => {
await esbuild.build({
...config,
banner: {
js: `(() => new EventSource("http://localhost:${port}").onmessage = () => location.reload())();`,
},
});
chokidar.watch(watchDirectories).on('all', (event, path) => {
console.log(`rebuilding ${path}`)
clients.forEach((res) => res.write('data: update\n\n'))
clients.length = 0
})
})();
http.createServer((req, res) => {
return clients.push(
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Access-Control-Allow-Origin": "*",
Connection: "keep-alive",
}),
);
}).listen(port);
} else {
esbuild
.build(config)
.catch(error => {
console.log(error)
process.exit(1)
})
}
x-base: &base
image: app-dev:1.0.0
volumes:
- .:/app:cached
- bundle:/gems
- /app/node_modules
x-app: &app
<<: *base
build:
target: builder
context: .
dockerfile: Dockerfile
args:
RAILS_ENV: ${RAILS_ENV:-development}
RAILS_MASTER_KEY: ${RAILS_MASTER_KEY}
tty: true
stdin_open: true
environment:
RAILS_ENV: ${RAILS_ENV:-development}
DATABASE_URL: ${DATABASE_URL:-postgres://postgres:password@db:5432/app_development}
REDIS_URL: redis://redis:6379
PORT: 3000
RAILS_LOG_TO_STDOUT: ${RAILS_LOG_TO_STDOUT}
RAILS_SERVE_STATIC_FILES: ${RAILS_SERVE_STATIC_FILES}
depends_on:
- db
- redis
x-assets: &assets
<<: *base
environment:
LIVE_RELOAD_PORT: 8082
services:
web:
<<: *app
command: 'bundle exec rails server -b 0.0.0.0 -p 3000'
ports:
- '3000:3000'
worker:
<<: *app
command: 'bundle exec sidekiq -C config/sidekiq.yml'
db:
image: postgres:14-alpine
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=app_development
ports:
- 5432
volumes:
- db_vol:/var/lib/postgresql/data
healthcheck:
test: pg_isready -U postgres -h 127.0.0.1
interval: 2s
timeout: 10s
redis:
image: redis:6.2.6-alpine
ports:
- 6379
healthcheck:
test: redis-cli ping
interval: 1s
timeout: 3s
retries: 30
volumes:
- redis_vol:/data
js:
<<: *assets
ports:
- '8082:8082'
command: 'yarn build:dev --watch'
css:
<<: *assets
command: 'yarn build:css:dev --watch'
volumes:
db_vol:
redis_vol:
bundle:
ARG RUBY_VERSION=3.1.2
FROM ruby:$RUBY_VERSION-bullseye as builder
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 \
LANG=C.UTF-8 \
BUNDLE_RETRY=3 \
BUNDLE_PATH=/gems
ARG RAILS_ENV=production
ENV RAILS_ENV $RAILS_ENV
# This is needed during the build process because when precompiling assets, the
# application boots up which in turn needs to access this variable.
ARG RAILS_MASTER_KEY
ENV RAILS_MASTER_KEY $RAILS_MASTER_KEY
ARG DEBIAN_FRONTEND="noninteractive"
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get update -qq \
&& apt-get -yq dist-upgrade \
&& apt-get install -yq --no-install-recommends \
nodejs postgresql-client libjemalloc2 \
vim libvips libglib2.0-0 libglib2.0-dev libpoppler-glib8 \
&& apt-get clean \
&& rm -rf /var/cache/apt/archives/* \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& truncate -s 0 /var/log/*log \
&& npm install --location=global yarn@1.22.17
WORKDIR /app
COPY package.json *yarn* Gemfile* ./
RUN yarn install --check-files && yarn cache clean \
&& bundle install --jobs "$(nproc)" \
&& rm -rf $BUNDLE_PATH/ruby/3.1.0/cache/* \
&& find $BUNDLE_PATH/ -name "*.c" -delete \
&& find $BUNDLE_PATH/ -name "*.o" -delete
COPY . ./
RUN if [ "${RAILS_ENV}" != "development" ]; then \
SECRET_KEY_BASE=dummyvalue bin/rails assets:precompile \
&& bin/rails assets:clean \
; fi
CMD ["bash"]
# This is the production image
FROM ruby:$RUBY_VERSION-slim-bullseye as app
ENV LANG=C.UTF-8 \
BUNDLE_RETRY=3 \
BUNDLE_PATH=/gems \
RAILS_ENV=production \
RACK_ENV=production \
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
ARG SC_SLUG_COMMIT
ENV SC_SLUG_COMMIT $SC_SLUG_COMMIT
ARG DEBIAN_FRONTEND="noninteractive"
WORKDIR /app
COPY . /app/
COPY bin/ ./bin
RUN chmod 0755 bin/*
# Need to figure out a way to ensure the corret deps are copied over to production
RUN apt-get update -qq \
&& apt-get -yq dist-upgrade \
&& apt-get install -yq --no-install-recommends \
postgresql-client libjemalloc2 \
vim libvips libglib2.0-0 libglib2.0-dev libpoppler-glib8 \
&& apt-get clean \
&& rm -rf /var/cache/apt/archives/* \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& truncate -s 0 /var/log/*log
COPY --from=builder /usr/local/bundle/config /usr/local/bundle/config
COPY --from=builder $BUNDLE_PATH $BUNDLE_PATH
COPY --from=builder /app/public /app/public
RUN bundle exec bootsnap precompile --gemfile app/ lib/
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["/usr/bin/entrypoint.sh"]
# Configure the main process to run when running the image
ARG PORT
EXPOSE $PORT
# CMD bundle exec rails server -b 0.0.0.0 -p $PORT
# Honestly this is so dumb but this is how heroku works
CMD ["./heroku/start"]
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
#!/bin/bash
PG_STATEMENT_TIMEOUT=90000 bundle exec rails db:migrate
#!/bin/bash
# ./heroku/start
# This is required because based on the process type that this is
# running on (web, worker, release), different things need to be
# executed.
set -e
if [[ $DYNO == "web"* ]]; then
bin/rails server -p $PORT
elif [[ $DYNO == "worker"* ]]; then
bundle exec sidekiq -C config/sidekiq.yml
elif [[ $DYNO == "release"* ]]; then
./release
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment