diff --git a/Dockerfile b/Dockerfile index 143d4043..e99c3fc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # el mismo repositorio de trabajo. Cuando tengamos CI/CD algunas cosas # como el tarball van a tener que cambiar porque ya vamos a haber hecho # un clone/pull limpio. -FROM sutty/sdk-ruby:latest as build +FROM alpine:3.9 as build MAINTAINER "f " ARG RAILS_MASTER_KEY @@ -13,10 +13,21 @@ ENV SECRET_KEY_BASE solo_es_necesaria_para_correr_rake ENV RAILS_ENV production ENV RAILS_MASTER_KEY=$RAILS_MASTER_KEY -# Para compilar los assets en brotli -RUN apk add --no-cache brotli libssh2 +RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake +RUN apk add --no-cache postgresql-libs git yarn brotli libssh2 -# Empezamos con la usuaria app creada por sdk-ruby +# https://github.com/rubygems/rubygems/issues/2918 +# https://gitlab.alpinelinux.org/alpine/aports/issues/10808 +COPY ./rubygems-platform-musl.patch /tmp/ +RUN cd /usr/lib/ruby/2.5.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch + +# Agregar el usuario +RUN addgroup -g 82 -S www-data +RUN adduser -s /bin/sh -G www-data -h /home/app -D app +RUN install -dm750 -o app -g www-data /home/app/web +RUN gem install --no-document bundler:2.0.2 + +# Empezamos con la usuaria app USER app # Vamos a trabajar dentro de este directorio WORKDIR /home/app/sutty @@ -24,25 +35,23 @@ WORKDIR /home/app/sutty # Copiamos solo el Gemfile para poder instalar las gemas necesarias COPY --chown=app:www-data ./Gemfile . COPY --chown=app:www-data ./Gemfile.lock . -# XXX: No usamos la flag --production porque luego no nos deja -# desinstalar las gemas de los assets -# RUN --mount=type=cache,target=/home/app/.ccache \ RUN bundle install --no-cache --path=./vendor --without='test development' # Vaciar la caché RUN rm vendor/ruby/2.5.0/cache/*.gem -# Limpiar las librerías nativas, esto ahorra más espacio y uso de -# memoria ya que no hay que cargar símbolos que no se van a usar. -RUN find vendor -name "*.so" | xargs -rn 1 strip --strip-unneeded # Copiar el repositorio git COPY --chown=app:www-data ./.git/ ./.git/ -# Hacer un tarball de los archivos desde el repositorio -RUN git archive -o ../sutty.tar.gz HEAD +# Hacer un clon limpio del repositorio en lugar de copiar todos los +# archivos +RUN cd .. && git clone sutty checkout + +WORKDIR /home/app/checkout +# Traer las gemas: +RUN mv ../web/vendor ./vendor +RUN mv ../web/.bundle ./.bundle -# Extraer archivos necesarios para compilar los assets -RUN tar xf ../sutty.tar.gz Rakefile config app bin yarn.lock package.json # Instalar secretos -COPY --chown=app:www-data ./config/credentials.yml.enc ./config/ +COPY --chown=app:root ./config/credentials.yml.enc ./config/ # Pre-compilar los assets RUN bundle exec rake assets:precompile # Comprimirlos usando brotli @@ -52,71 +61,48 @@ RUN find public -type f -name "*.gz" | sed -re "s/\.gz$//" | xargs -r brotli -k # assets ya están pre-compilados. RUN sed -re "/(uglifier|bootstrap|coffee-rails)/d" -i Gemfile RUN bundle clean +RUN rm -rf ./node_modules ./tmp/cache ./.git # Contenedor final -FROM sutty/monit:latest +FROM sutty/monit:3.9 ENV RAILS_ENV production # Instalar las dependencias, separamos la librería de base de datos para # poder reutilizar este primer paso desde otros contenedores RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake +RUN apk add --no-cache postgresql-libs libssh2 file rsync git # Chequear que la versión de ruby sea la correcta RUN test "2.5.7" = `ruby -e 'puts RUBY_VERSION'` -RUN apk add --no-cache postgresql-libs libssh2 -# Necesitamos yarn para que Jekyll pueda generar los sitios -# XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso -# principal -RUN apk add --no-cache yarn -# Instalar foreman para poder correr los servicios -RUN gem install --no-document --no-user-install foreman -RUN apk add --no-cache file - -# Agregar el grupo del servidor web -RUN addgroup -g 82 -S www-data -# Agregar la usuaria -RUN adduser -s /bin/sh -G www-data -h /srv/http -D app - # https://github.com/rubygems/rubygems/issues/2918 # https://gitlab.alpinelinux.org/alpine/aports/issues/10808 COPY ./rubygems-platform-musl.patch /tmp/ RUN cd /usr/lib/ruby/2.5.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch +# Necesitamos yarn para que Jekyll pueda generar los sitios +# XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso +# principal +RUN apk add --no-cache yarn +# Instalar foreman para poder correr los servicios +RUN gem install --no-document --no-user-install bundler foreman + +# Agregar el grupo del servidor web y la usuaria +RUN addgroup -g 82 -S www-data +RUN adduser -s /bin/sh -G www-data -h /srv/http -D app + # Convertirse en app para instalar USER app -WORKDIR /srv/http - -# Traer los archivos y colocarlos donde van definitivamente -COPY --from=build --chown=app:www-data /home/app/sutty.tar.gz /tmp/ -RUN tar xf /tmp/sutty.tar.gz -# Publicar el código! -RUN mv /tmp/sutty.tar.gz ./public/ - -# Traer los assets compilados y las gemas -COPY --from=build /home/app/sutty/public/assets public/assets -COPY --from=build /home/app/sutty/public/packs public/packs -COPY --from=build /home/app/sutty/vendor vendor -COPY --from=build /home/app/sutty/.bundle .bundle -COPY --from=build /home/app/sutty/Gemfile Gemfile -COPY --from=build /home/app/sutty/Gemfile.lock Gemfile.lock +COPY --from=build --chown=app:www-data /home/app/checkout /srv/http # Volver a root para cerrar la compilación USER root -# Convertir la aplicación en solo lectura -#RUN chown -R root:root /srv/http -#RUN chmod -R o=g /srv/http -#RUN chown -R app:www-data _deploy _sites - # Sincronizar los assets a un directorio compartido -RUN apk add --no-cache rsync COPY ./sync_assets.sh /usr/local/bin/sync_assets RUN chmod 755 /usr/local/bin/sync_assets # Instalar la configuración de monit y comprobarla RUN install -m 640 -o root -g root ./monit.conf /etc/monit.d/sutty.conf -RUN monit -t -RUN apk add --no-cache git # Mantener estos directorios! VOLUME "/srv/http/_deploy" diff --git a/Makefile b/Makefile index 226328d2..17d93c55 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,13 @@ clean: build: docker build --build-arg="RAILS_MASTER_KEY=`cat config/master.key`" -t sutty/sutty . +save: + docker save sutty/sutty:latest | gzip > sutty.latest.gz + scp sutty.latest.gz root@sutty.nl: + +load: + ssh root@sutty.nl sh -c "gunzip -c sutty.latest.gz | docker load" + # Crear el directorio donde se almacenan las gemas binarias ../gems/: mkdir -p $@ diff --git a/config/puma.rb b/config/puma.rb index 872346ff..629b81fe 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -38,3 +38,22 @@ preload_app! plugin :tmp_restart pidfile 'tmp/puma.pid' + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +before_fork do + ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +on_worker_boot do + ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +end diff --git a/sync_assets.sh b/sync_assets.sh index 167d6205..1c1a6ca1 100644 --- a/sync_assets.sh +++ b/sync_assets.sh @@ -2,4 +2,4 @@ # Sincronizar assets desde public a _public para que estén disponibles # en el contenedor web. -rsync -a --delete-after public/ _public/ +rsync -a --delete-after /srv/http/public/ /srv/http/_public/ diff --git a/vendor/.keep b/vendor/.keep deleted file mode 100644 index e69de29b..00000000