diff --git a/Dockerfile b/Dockerfile index 5496455..dc40e0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,3 @@ -# syntax=docker/dockerfile:1 - ARG RUBY_VERSION=3.3 FROM ruby:${RUBY_VERSION}-alpine @@ -7,29 +5,36 @@ RUN apk add --no-cache --update \ build-base \ postgresql-client \ postgresql-dev \ - tzdata + git \ + tzdata \ + vim bash # Set up entrypoint WORKDIR / -COPY entrypoint.sh . -RUN chmod +x entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -# Set up bundle path +COPY docker-entrypoint.sh . +RUN chmod +x /docker-entrypoint.sh +ENTRYPOINT ["/docker-entrypoint.sh"] +WORKDIR /docker-entrypoint.d +COPY docker-entrypoint.d/10-remove-pid.sh . +COPY docker-entrypoint.d/20-database-url.sh . +COPY docker-entrypoint.d/30-bundle-install.sh . +RUN chmod +x /docker-entrypoint.d/*.sh + +# Set up bundler RUN mkdir -p /usr/local/bundle -ENV BUNDLE_PATH /usr/local/bundle +ENV BUNDLE_PATH=/usr/local/bundle +RUN gem install bundler || gem install bundler -v 2.4.22 # This fallback supports older versions of ruby/bundler # Set up pid file RUN mkdir -p /var/run/ -ENV PIDFILE /var/run/puma.pid +ENV PIDFILE=/var/run/puma.pid # Configure default environment setup WORKDIR /app -ENV RAILS_ENV production -ENV RAILS_LOG_TO_STDOUT true +ENV RAILS_LOG_TO_STDOUT=true -ENV BINDING 0.0.0.0 -ENV PORT 80 +ENV BINDING=0.0.0.0 +ENV PORT=80 EXPOSE 80 CMD ["bundle", "exec", "rails", "server"] diff --git a/Makefile b/Makefile index 996b26c..8acfc43 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,14 @@ +RUBY_VERSIONS_FILE := ruby_versions.txt + +.PHONY: build build: - docker buildx bake + @while IFS= read -r version; do \ + echo "Building for Ruby $$version..."; \ + RUBY_VERSION=$$version docker buildx bake; \ + done < $(RUBY_VERSIONS_FILE) push: - docker buildx bake --push + @while IFS= read -r version; do \ + echo "Building and pushing for Ruby $$version..."; \ + RUBY_VERSION=$$version docker buildx bake --push; \ + done < $(RUBY_VERSIONS_FILE) diff --git a/README.md b/README.md index e74080c..e7f74b9 100644 --- a/README.md +++ b/README.md @@ -14,33 +14,23 @@ This image is very opinionated; however, not restrictive. ### Ruby 3.3 - [ruby3.3, ruby3, latest](Dockerfile) -- [ruby3.3-local, ruby3-local, local](local.Dockerfile) - [ruby3.3-webapp, ruby3-webapp, webapp](webapp/Dockerfile) -- [ruby3.3-webapp-local, ruby3-webapp-local, webapp-local](webapp/local.Dockerfile) ### Ruby 3.2 - [ruby3.2](Dockerfile) -- [ruby3.2-local](local.Dockerfile) - [ruby3.2-webapp](webapp/Dockerfile) -- [ruby3.2-webapp-local](webapp/local.Dockerfile) - ### Ruby 3.1 - [ruby3.1](Dockerfile) -- [ruby3.1-local](local.Dockerfile) - [ruby3.1-webapp](webapp/Dockerfile) -- [ruby3.1-webapp-local](webapp/local.Dockerfile) ### Ruby 3.0 - [ruby3.0](Dockerfile) -- [ruby3.0-local](local.Dockerfile) - [ruby3.0-webapp](webapp/Dockerfile) -- [ruby3.0-webapp-local](webapp/local.Dockerfile) ### Ruby 2.7 - [ruby2.7](Dockerfile) -- [ruby2.7-local](local.Dockerfile) - [ruby2.7-webapp](webapp/Dockerfile) -- [ruby2.7-webapp-local](webapp/local.Dockerfile) ## Production vs Local diff --git a/docker-bake.hcl b/docker-bake.hcl index 1ace1fe..4de5ca4 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -1,264 +1,23 @@ -group "default" { - targets = [ - "ruby3-3", - "ruby3-3-local", - "ruby3-3-webapp", - "ruby3-3-webapp-local", - - "ruby3-2", - "ruby3-2-local", - "ruby3-2-webapp", - "ruby3-2-webapp-local", - - "ruby3-1", - "ruby3-1-local", - "ruby3-1-webapp", - "ruby3-1-webapp-local", - - "ruby3-0", - "ruby3-0-local", - "ruby3-0-webapp", - "ruby3-0-webapp-local", - - "ruby2-7", - "ruby2-7-local", - "ruby2-7-webapp", - "ruby2-7-webapp-local", - ] -} - -target "ruby3-3" { - dockerfile = "Dockerfile" - tags = [ - "nullstone/rails:ruby3.3", - "nullstone/rails:ruby3", - "nullstone/rails", - ] - args = { - "RUBY_VERSION" = "3.3" - } -} - -target "ruby3-3-local" { - dockerfile = "local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.3-local", - "nullstone/rails:ruby3-local", - "nullstone/rails:local", - ] - args = { - "RUBY_VERSION" = "3.3" - } -} - -target "ruby3-3-webapp" { - dockerfile = "webapp/Dockerfile" - tags = [ - "nullstone/rails:ruby3.3-webapp", - "nullstone/rails:ruby3-webapp", - "nullstone/rails:webapp" - ] - args = { - "RUBY_VERSION" = "3.3" - } -} - -target "ruby3-3-webapp-local" { - dockerfile = "webapp/local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.3-webapp-local", - "nullstone/rails:ruby3-webapp-local", - "nullstone/rails:webapp-local" - ] - args = { - "RUBY_VERSION" = "3.3" - } -} - -group "group-ruby3-2" { - targets = [ - "ruby3-2", - "ruby3-2-local", - "ruby3-2-webapp", - "ruby3-2-webapp-local", - ] -} - -target "ruby3-2" { - dockerfile = "Dockerfile" - tags = ["nullstone/rails:ruby3.2"] - args = { - "RUBY_VERSION" = "3.2.2" - } -} - -target "ruby3-2-local" { - dockerfile = "local.Dockerfile" - tags = ["nullstone/rails:ruby3.2-local"] - args = { - "RUBY_VERSION" = "3.2.2" - } -} - -target "ruby3-2-webapp" { - dockerfile = "webapp/Dockerfile" - tags = ["nullstone/rails:ruby3.2-webapp"] - args = { - "RUBY_VERSION" = "3.2.2" - } -} - -target "ruby3-2-webapp-local" { - dockerfile = "webapp/local.Dockerfile" - tags = ["nullstone/rails:ruby3.2-webapp-local"] - args = { - "RUBY_VERSION" = "3.2.2" - } -} - -group "group-ruby3-1" { - targets = [ - "ruby3-1", - "ruby3-1-local", - "ruby3-1-webapp", - "ruby3-1-webapp-local", - ] -} - -target "ruby3-1" { - dockerfile = "Dockerfile" - tags = [ - "nullstone/rails:ruby3.1", - ] - args = { - "RUBY_VERSION" = "3.1" - } -} - -target "ruby3-1-local" { - dockerfile = "local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.1-local", - ] - args = { - "RUBY_VERSION" = "3.1" - } -} - -target "ruby3-1-webapp" { - dockerfile = "webapp/Dockerfile" - tags = [ - "nullstone/rails:ruby3.1-webapp", - ] - args = { - "RUBY_VERSION" = "3.1" - } -} - -target "ruby3-1-webapp-local" { - dockerfile = "webapp/local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.1-webapp-local", - ] - args = { - "RUBY_VERSION" = "3.1" - } -} - -group "group-ruby3-0" { - targets = [ - "ruby3-0", - "ruby3-0-local", - "ruby3-0-webapp", - "ruby3-0-webapp-local", - ] -} - -target "ruby3-0" { - dockerfile = "Dockerfile" - tags = [ - "nullstone/rails:ruby3.0" - ] - args = { - "RUBY_VERSION" = "3.0" - } +variable "RUBY_VERSION" { + default = "3.4" } -target "ruby3-0-local" { - dockerfile = "local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.0-local" - ] - args = { - "RUBY_VERSION" = "3.0" - } -} - -target "ruby3-0-webapp" { - dockerfile = "webapp/Dockerfile" - tags = [ - "nullstone/rails:ruby3.0-webapp" - ] - args = { - "RUBY_VERSION" = "3.0" - } -} - -target "ruby3-0-webapp-local" { - dockerfile = "webapp/local.Dockerfile" - tags = [ - "nullstone/rails:ruby3.0-webapp-local" - ] - args = { - "RUBY_VERSION" = "3.0" - } -} - -group "group-ruby2-7" { - targets = [ - "ruby2-7", - "ruby2-7-local", - "ruby2-7-webapp", - "ruby2-7-webapp-local", - ] +group "default" { + targets = ["normal", "webapp"] } -target "ruby2-7" { +target "normal" { dockerfile = "Dockerfile" - tags = [ - "nullstone/rails:ruby2.7" - ] + tags = ["nullstone/rails:ruby${RUBY_VERSION}"] args = { - "RUBY_VERSION" = "2.7" + RUBY_VERSION = RUBY_VERSION } } -target "ruby2-7-local" { - dockerfile = "local.Dockerfile" - tags = [ - "nullstone/rails:ruby2.7-local" - ] - args = { - "RUBY_VERSION" = "2.7" - } -} - -target "ruby2-7-webapp" { +target "webapp" { dockerfile = "webapp/Dockerfile" - tags = [ - "nullstone/rails:ruby2.7-webapp" - ] - args = { - "RUBY_VERSION" = "2.7" - } -} - -target "ruby2-7-webapp-local" { - dockerfile = "webapp/local.Dockerfile" - tags = [ - "nullstone/rails:ruby2.7-webapp-local" - ] + tags = ["nullstone/rails:ruby${RUBY_VERSION}-webapp"] args = { - "RUBY_VERSION" = "2.7" + RUBY_VERSION = RUBY_VERSION } } diff --git a/docker-entrypoint.d/10-remove-pid.sh b/docker-entrypoint.d/10-remove-pid.sh new file mode 100644 index 0000000..92fc33c --- /dev/null +++ b/docker-entrypoint.d/10-remove-pid.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +echo "Removing pid file" +rm -f "${PIDFILE}" diff --git a/entrypoint.sh b/docker-entrypoint.d/20-database-url.sh similarity index 81% rename from entrypoint.sh rename to docker-entrypoint.d/20-database-url.sh index 6b4b006..60d2c30 100644 --- a/entrypoint.sh +++ b/docker-entrypoint.d/20-database-url.sh @@ -2,9 +2,6 @@ set -e -# Remove puma.pid so that a docker restart doesn't prevent puma from starting -rm -f /var/run/puma.pid - # Configure DATABASE_URL if POSTGRES_URL is set if [ -n "${POSTGRES_URL}" ]; then echo "Setting DB_ADAPTER=postgresql" @@ -20,5 +17,3 @@ if [ -n "${MYSQL_URL}" ]; then echo "Configuring DATABASE_URL using MYSQL_URL" export DATABASE_URL="${MYSQL_URL}" fi - -exec "$@" diff --git a/docker-entrypoint.d/30-bundle-install.sh b/docker-entrypoint.d/30-bundle-install.sh new file mode 100644 index 0000000..42c3803 --- /dev/null +++ b/docker-entrypoint.d/30-bundle-install.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +set -e + +if [ "${NULLSTONE_ENV}" = "local" ]; then + echo "Verifying and installing gems..." + bundle check || bundle install +else + echo "Skipping bundle install (not a local environment)" +fi diff --git a/docker-entrypoint.d/40-node-install.sh b/docker-entrypoint.d/40-node-install.sh new file mode 100644 index 0000000..fcc428d --- /dev/null +++ b/docker-entrypoint.d/40-node-install.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +if [ "${NULLSTONE_ENV}" = "local" ]; then + if [ -f "yarn.lock" ]; then + echo "Installing yarn dependencies..." + yarn install + fi + if [ -f "package-lock.json" ]; then + echo "Installing npm dependencies..." + npm install + fi +else + echo "Skipping node install (not a local environment)" +fi \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..265f13e --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e + +if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then + echo >&2 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" + + echo >&2 "$0: Looking for shell scripts in /docker-entrypoint.d/" + find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + echo >&2 "$0: Launching $f"; + # shellcheck source=/docker-entrypoint.d/{script.sh} + . "$f" + else + # warn on shell scripts without exec bit + echo >&2 "$0: Ignoring $f, not executable"; + fi + ;; + *) echo >&2 "$0: Ignoring $f";; + esac + done + + echo >&2 "$0: Configuration complete; ready for start up" +else + echo >&2 "$0: No files found in /docker-entrypoint.d/, skipping configuration" +fi + +exec "$@" diff --git a/local.Dockerfile b/local.Dockerfile deleted file mode 100644 index 7d78dc6..0000000 --- a/local.Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -# syntax=docker/dockerfile:1 - -ARG RUBY_VERSION=3.3 -FROM ruby:${RUBY_VERSION}-alpine - -RUN apk add --no-cache --update \ - build-base \ - postgresql-client \ - postgresql-dev \ - tzdata - -# Set up entrypoint -WORKDIR / -COPY local.entrypoint.sh . -RUN chmod +x local.entrypoint.sh -ENTRYPOINT ["/local.entrypoint.sh"] - -# Set up bundle path -RUN mkdir -p /usr/local/bundle -ENV BUNDLE_PATH /usr/local/bundle - -# Set up pid file -RUN mkdir -p /var/run/ -ENV PIDFILE /var/run/puma.pid - -# Configure default environment setup -WORKDIR /app -ENV RAILS_ENV development -ENV RAILS_LOG_TO_STDOUT true - -ENV BINDING 0.0.0.0 -ENV PORT 80 -EXPOSE 80 - -CMD ["bundle", "exec", "rails", "server"] diff --git a/local.entrypoint.sh b/local.entrypoint.sh deleted file mode 100644 index 587554f..0000000 --- a/local.entrypoint.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -set -e - -echo "Installing bundler..." -gem install bundler -echo "Verifying and installing gems..." -bundle check || bundle install - -if [ -f "yarn.lock" ]; then - echo "Installing yarn dependencies..." - yarn install -fi -if [ -f "package-lock.json" ]; then - echo "Installing npm dependencies..." - npm install -fi - -# Remove puma.pid so that a docker restart doesn't prevent puma from starting -rm -f /var/run/puma.pid - -# Configure DATABASE_URL if POSTGRES_URL is set -if [ -n "${POSTGRES_URL}" ]; then - echo "Setting DB_ADAPTER=postgresql" - export DB_ADAPTER=postgresql - echo "Configuring DATABASE_URL using POSTGRES_URL" - export DATABASE_URL="${POSTGRES_URL}" -fi - -# Configure DATABASE_URL if MYSQL_URL is set -if [ -n "${MYSQL_URL}" ]; then - echo "Setting DB_ADAPTER=mysql2" - export DB_ADAPTER=mysql2 - echo "Configuring DATABASE_URL using MYSQL_URL" - export DATABASE_URL="${MYSQL_URL}" -fi - -exec "$@" diff --git a/ruby_versions.txt b/ruby_versions.txt new file mode 100644 index 0000000..83a5389 --- /dev/null +++ b/ruby_versions.txt @@ -0,0 +1,27 @@ +3.4 +3.4.1 +3.4.2 +3.3 +3.3.0 +3.3.1 +3.3.2 +3.3.3 +3.3.4 +3.3.5 +3.3.6 +3.3.7 +3.2 +3.2.0 +3.2.1 +3.2.2 +3.2.3 +3.2.4 +3.2.5 +3.2.6 +3.2.7 +3.1 +3.1.6 +3.0 +3.0.7 +2.7 +2.7.8 diff --git a/webapp/Dockerfile b/webapp/Dockerfile index c50335f..df09c1d 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -1,5 +1,3 @@ -# syntax=docker/dockerfile:1 - ARG RUBY_VERSION=3.3 FROM ruby:${RUBY_VERSION}-alpine @@ -7,8 +5,10 @@ RUN apk add --no-cache --update \ build-base \ postgresql-client \ postgresql-dev \ - nodejs yarn \ - tzdata + git \ + nodejs npm yarn \ + tzdata \ + vim bash VOLUME /etc/nginx/conf.d VOLUME /etc/nginx/templates @@ -18,25 +18,31 @@ COPY etc/ /etc/ # Set up entrypoint WORKDIR / -COPY entrypoint.sh . -RUN chmod +x entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -# Set up bundle path +COPY docker-entrypoint.sh . +RUN chmod +x /docker-entrypoint.sh +ENTRYPOINT ["/docker-entrypoint.sh"] +WORKDIR /docker-entrypoint.d +COPY docker-entrypoint.d/10-remove-pid.sh . +COPY docker-entrypoint.d/20-database-url.sh . +COPY docker-entrypoint.d/30-bundle-install.sh . +COPY docker-entrypoint.d/40-node-install.sh . +RUN chmod +x /docker-entrypoint.d/*.sh + +# Set up bundler RUN mkdir -p /usr/local/bundle -ENV BUNDLE_PATH /usr/local/bundle +ENV BUNDLE_PATH=/usr/local/bundle +RUN gem install bundler || gem install bundler -v 2.4.22 # This fallback supports older versions of ruby/bundler # Set up pid file RUN mkdir -p /var/run/ -ENV PIDFILE /var/run/puma.pid +ENV PIDFILE=/var/run/puma.pid # Configure default environment setup WORKDIR /app -ENV RAILS_ENV production -ENV RAILS_LOG_TO_STDOUT true +ENV RAILS_LOG_TO_STDOUT=true -ENV BINDING 0.0.0.0 -ENV PORT 9000 +ENV BINDING=0.0.0.0 +ENV PORT=9000 EXPOSE 9000 CMD ["bundle", "exec", "rails", "server"] diff --git a/webapp/local.Dockerfile b/webapp/local.Dockerfile deleted file mode 100644 index d3f5fd7..0000000 --- a/webapp/local.Dockerfile +++ /dev/null @@ -1,42 +0,0 @@ -# syntax=docker/dockerfile:1 - -ARG RUBY_VERSION=3.3 -FROM ruby:${RUBY_VERSION}-alpine - -RUN apk add --no-cache --update \ - build-base \ - postgresql-client \ - postgresql-dev \ - nodejs yarn \ - tzdata - -VOLUME /etc/nginx/conf.d -VOLUME /etc/nginx/templates -VOLUME /app/public - -COPY etc/ /etc/ - -# Set up entrypoint -WORKDIR / -COPY local.entrypoint.sh . -RUN chmod +x local.entrypoint.sh -ENTRYPOINT ["/local.entrypoint.sh"] - -# Set up bundle path -RUN mkdir -p /usr/local/bundle -ENV BUNDLE_PATH /usr/local/bundle - -# Set up pid file -RUN mkdir -p /var/run/ -ENV PIDFILE /var/run/puma.pid - -# Configure default environment setup -WORKDIR /app -ENV RAILS_ENV development -ENV RAILS_LOG_TO_STDOUT true - -ENV BINDING 0.0.0.0 -ENV PORT 9000 -EXPOSE 9000 - -CMD ["bundle", "exec", "rails", "server"]