Skip to content

Commit

Permalink
Add Dockerfile.azure with SSH, remove CONTAINER_ID and cms constraint (
Browse files Browse the repository at this point in the history
…#658)

* Remove CONTAINER_ID, add SSH

- CONTAINER_ID was only used for Google Optimize, which is discontinued
- SSH will be needed for ongoing maintenance by developers

see https://learn.microsoft.com/en-gb/azure/app-service/configure-custom-container?tabs=alpine&pivots=container-linux#enable-ssh

* Add Dockerfile.azure, SSH
  • Loading branch information
ebrett authored Oct 23, 2023
1 parent 2242bf7 commit 512d54d
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 29 deletions.
3 changes: 3 additions & 0 deletions .docker-profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
echo "Welcome to the Help for Early Years Providers Application"

export PATH=$PATH:/usr/local/bin:/user/local/bundle/bin
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ RAILS_ENV=development
WEBPACKER_DEV_SERVER_HOST=0.0.0.0
FEEDBACK_URL=
SIGNUP_URL=
TRACKING_ID=
6 changes: 5 additions & 1 deletion .github/workflows/azure-deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.azure
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:builder
Expand All @@ -76,6 +77,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.azure
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:gems-node-modules
Expand All @@ -87,6 +89,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.azure
build-args: BUILDKIT_INLINE_CACHE=1
cache-from: |
${{ env.DOCKER_IMAGE }}-dev:assets-precompile
Expand All @@ -98,11 +101,12 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.azure
build-args: |
BUILDKIT_INLINE_CACHE=1
SHA=${{ github.sha }}
cache-from: |
type=registry,ref=${{ env.DOCKER_IMAGE }}-prod:latest
type=registry,ref=${{ env.DOCKER_IMAGE }}:latest
push: true
tags: |
${{ env.DOCKER_IMAGE }}:latest
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ COPY --from=assets-precompile /usr/local/bundle/ usr/local/bundle/
# The application runs from /app
WORKDIR /app

COPY .docker-profile /root/.profile

# Use the following for development testing
CMD bundle exec rails db:migrate && bundle exec rails server -b 0.0.0.0

Expand Down
137 changes: 137 additions & 0 deletions Dockerfile.azure
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

# To use or update to a ruby version, change {BASE_RUBY_IMAGE}
ARG BASE_RUBY_IMAGE=ruby:2.7.2-alpine

# BASE_RUBY_IMAGE_WITH_GEMS_AND_NODE_MODULES will defalt to help-for-early-years-gems-node-modules
# building all layers above it if a value is not specified during the build
ARG BASE_RUBY_IMAGE_WITH_GEMS_AND_NODE_MODULES=help-for-early-years-providers-gems-node-modules

# Stage 1: Download gems and node modules
FROM ${BASE_RUBY_IMAGE} AS builder

# Set bundler version
ENV BUNDLER_VERSION=2.2.26

# Dependencies for the build
# git: version manager
# nodejs: JavaScript runtime built on Chrome's V8 JavaScript engine
# yarn: node package manager
# postgresql-dev: postgres driver and libraries
ARG BUILD_DEPS="git gcc libc-dev make nodejs yarn npm shared-mime-info python2 postgresql-dev build-base libxml2-dev libxslt-dev ttf-ubuntu-font-family"

WORKDIR /app

COPY Gemfile Gemfile.lock package.json yarn.lock .ruby-version ./

RUN apk -U upgrade && \
apk add --update --no-cache --virtual .gem-installdeps $BUILD_DEPS && \
gem update --system && \
find / -wholename '*default/bundler-*.gemspec' -delete && \
rm -rf /usr/local/bundle/bin/bundle && \
gem install bundler -v ${BUNDLER_VERSION} --no-document && \
bundler -v && \
bundle config set no-cache 'true' && \
bundle config set no-binstubs 'true' && \
bundle --retry=5 --jobs=4 --without=development test && \
yarn install --check-files --production && \
apk del .gem-installdeps && \
rm -rf /usr/local/bundle/cache && \
find /usr/local/bundle/gems -name "*.c" -delete && \
find /usr/local/bundle/gems -name "*.h" -delete && \
find /usr/local/bundle/gems -name "*.o" -delete

# Stage 2: reduce size of gems-node-modules and only keep required files
# Add the timezone as it's not configured by default in Alpine
FROM ${BASE_RUBY_IMAGE} as help-for-early-years-providers-gems-node-modules

RUN apk -U upgrade && \
apk add --update --no-cache nodejs yarn tzdata libpq libxml2 libxslt graphviz shared-mime-info && \
echo "Europe/London" > /etc/timezone && \
cp /usr/share/zoneinfo/Europe/London /etc/localtime

COPY --from=builder /app /app
COPY --from=builder /usr/local/bundle /usr/local/bundle

# Stage 3: assets-precompile, precompile assets and remove compile dependencies
FROM ${BASE_RUBY_IMAGE_WITH_GEMS_AND_NODE_MODULES} as assets-precompile

ARG RAILS_ENV=production
ENV GOVUK_APP_DOMAIN=www.gov.uk \
GOVUK_WEBSITE_ROOT=https://www.gov.uk \
RAILS_ENV=${RAILS_ENV} \
AUTHORIZED_HOSTS=127.0.0.1 \
SECRET_KEY_BASE=TestKey \
IGNORE_SECRETS_FOR_BUILD=1

# RACK_ENV=${RAILS_ENV} \
# LANG=C.UTF-8 \
# BUNDLE_JOBS=4 \
# BUNDLE_RETRY=3 \
# BUNDLE_PATH=/usr/local/bundle \
# RAILS_SERVE_STATIC_FILES=true \
# RAILS_LOG_TO_STDOUT=true \

WORKDIR /app
COPY . .

RUN bundle exec rake assets:precompile && \
apk del nodejs yarn && \
rm -rf yarn.lock && \
rm -rf tmp/* log/* node_modules /usr/local/share/.cache /tmp/*

# Stage 4: production, copy application code and compiled assets to base ruby image
# Depends on assets-precompile stage which can be cached from a pre-build image
# by specifiying a fully qualified image name or will default to packages-prod
# thereby rebuilding all 3 stages above.
# If an existing base image name is specified Stage 1 & 2 will not be build and
# gems and dev packages will be used from the supplied image.

FROM ${BASE_RUBY_IMAGE} as production
ARG SHA
ENV AUTHORIZED_HOSTS=127.0.0.1 \
SHA=${SHA}

RUN apk -U upgrade && \
apk add --update --no-cache tzdata libpq libxml2 libxslt graphviz shared-mime-info && \
echo "Europe/London" > /etc/timezone && \
cp /usr/share/zoneinfo/Europe/London /etc/localtime

COPY --from=assets-precompile /app /app
COPY --from=assets-precompile /usr/local/bundle/ usr/local/bundle/

# The application runs from /app
WORKDIR /app

COPY sshd_config /etc/ssh/
COPY ./entrypoints/docker-entrypoint.sh ./
COPY .docker-profile /root/.profile

# Start and enable SSH
RUN apk add openssh \
&& echo "root:Docker!" | chpasswd \
&& chmod +x ./docker-entrypoint.sh \
&& cd /etc/ssh/ \
&& ssh-keygen -A

EXPOSE 3000 2222

ENTRYPOINT [ "./docker-entrypoint.sh" ]

# Use the following for development testing
CMD bundle exec rails db:migrate && bundle exec rails server -b 0.0.0.0

# Otherwise use the following
# CMD bundle exec rails db:migrate:ignore_concurrent_migration_exceptions && bundle exec rails server -b 0.0.0.0

# We migrate and ignore concurrent_migration_exceptions because we deploy to
# multiple instances at the same time.
#
# Under these conditions each instance will try to run migrations. Rails uses a
# database lock to prevent them stepping on each another. If they happen to,
# a ConcurrentMigrationError exception is thrown, the command exits 1, and
# the server will not start thanks to the shell &&.
#
# We swallow the exception and run the server anyway, because we prefer running
# new code on an old schema (which will be updated a moment later) to running
# old code on the new schema (which will require another deploy or other manual
# intervention to correct).
2 changes: 0 additions & 2 deletions app/views/layouts/_analytics_header.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<script src="https://www.googleoptimize.com/optimize.js?id=<%= GoogleAnalytics::CONTAINER_ID %>"></script>

<!-- Google tag (gtag.js) -->
<script async src=<%= "https://www.googletagmanager.com/gtag/js?id=#{GoogleAnalytics::TRACKING_ID}" %>></script>
<script>
Expand Down
3 changes: 1 addition & 2 deletions config/initializers/google_analytics.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

module GoogleAnalytics
CONTAINER_ID = Rails.application.credentials.dig :google_analytics, Rails.configuration.space.to_sym, :container_id
TRACKING_ID = Rails.application.credentials.dig :google_analytics, Rails.configuration.space.to_sym, :tracking_id
TRACKING_ID = ENV.fetch("TRACKING_ID", "#TRACKING_ID_env_var_missing")
JS_URL = "https://www.googletagmanager.com/ns.html?id=#{GoogleAnalytics::TRACKING_ID}"
end
46 changes: 22 additions & 24 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,32 @@

resources :settings, only: %i[show create]

constraints CmsRouteConstraint.new do
devise_for :users
devise_scope :user do
get "sign_in", to: "devise/sessions#new"
delete "sign_out", to: "devise/sessions#destroy"
end
devise_for :users
devise_scope :user do
get "sign_in", to: "devise/sessions#new"
delete "sign_out", to: "devise/sessions#destroy"
end

namespace :admin do
root to: "users#index"
resources :users
resources :articles do
namespace :admin do
root to: "users#index"
resources :users
resources :articles do
post "publish", on: :member
post "unpublish", on: :member
end
resources :content_pages, path: "pages" do
get "versions", on: :member
get "preview_of_live", on: :member
post "unpublish", on: :member
resources :content_page_versions do
get "preview_of_draft", on: :member
post "publish", on: :member
post "unpublish", on: :member
end
resources :content_pages, path: "pages" do
get "versions", on: :member
get "preview_of_live", on: :member
post "unpublish", on: :member
resources :content_page_versions do
get "preview_of_draft", on: :member
post "publish", on: :member
end
end
resources :content_blocks, path: "blocks", only: %i[index new edit create update]
resources :content_assets, path: "assets"
# This is not a resource route
post "preview_markdown", to: "content_pages#preview"
end
resources :content_blocks, path: "blocks", only: %i[index new edit create update]
resources :content_assets, path: "assets"
# This is not a resource route
post "preview_markdown", to: "content_pages#preview"
end

%w[accessibility-statement contact-us disclaimer child-development-training].each do |static_page|
Expand Down
2 changes: 2 additions & 0 deletions entrypoints/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi

/usr/sbin/sshd

bundle exec rake db:prepare db:seed

# Start the application
Expand Down
12 changes: 12 additions & 0 deletions sshd_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Port 2222
ListenAddress 0.0.0.0
LoginGraceTime 180
X11Forwarding yes
Ciphers aes128-cbc,3des-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr
MACs hmac-sha1,hmac-sha1-96
StrictModes yes
SyslogFacility DAEMON
PasswordAuthentication yes
PermitEmptyPasswords no
PermitRootLogin yes
Subsystem sftp internal-sftp

0 comments on commit 512d54d

Please sign in to comment.