Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lessons/220/deploy/ruby-app/0-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ruby-app
namespace: default
data:
database.yml: |
default: &default
adapter: postgresql
encoding: unicode
timeout: 5000
host: postgresql.antonputra.pvt
database: mydb
pool: 50
username: rails
password: devops123

development:
!!merge <<: *default

production:
!!merge <<: *default
86 changes: 86 additions & 0 deletions lessons/220/deploy/ruby-app/1-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruby-app
namespace: default
spec:
replicas: 2
strategy:
type: Recreate
selector:
matchLabels:
app: ruby-app
template:
metadata:
labels:
app: ruby-app
spec:
terminationGracePeriodSeconds: 0
initContainers:
- name: migration
image: aputra/ruby-app-220:v5
command: ['sh', '-c', "/rails/bin/rake db:migrate"]
volumeMounts:
- name: config
mountPath: /rails/db/config.yml
subPath: config.yml
containers:
- name: ruby-app
image: aputra/ruby-app-220:v5
ports:
- name: http
containerPort: 8080
- name: WORKERS_NUM
value: "2" # 0 for single-mode
- name: RAILS_MAX_THREADS
value: "2"
resources:
requests:
memory: 512Mi
cpu: 750m
limits:
memory: 512Mi
cpu: 1000m
readinessProbe:
httpGet:
path: /up
port: http
livenessProbe:
httpGet:
path: /up
port: http
volumeMounts:
- name: config
mountPath: /rails/db/config.yml
subPath: config.yml
volumes:
- name: config
configMap:
name: ruby-app
tolerations:
- effect: NoSchedule
operator: Exists
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ruby-app
topologyKey: "kubernetes.io/hostname"
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node
operator: In
values:
- general
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
14 changes: 14 additions & 0 deletions lessons/220/deploy/ruby-app/2-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: v1
kind: Service
metadata:
name: ruby-app
namespace: default
spec:
ports:
- name: http
port: 8080
targetPort: http
selector:
app: ruby-app
type: ClusterIP
17 changes: 17 additions & 0 deletions lessons/220/deploy/ruby-app/3-pod-monitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: ruby-app
namespace: monitoring
labels:
prometheus: main
spec:
namespaceSelector:
matchNames:
- default
selector:
matchLabels:
app: ruby-app
podMetricsEndpoints:
- port: http
17 changes: 17 additions & 0 deletions lessons/220/deploy/ruby-app/4-client-pod-monitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: rails-client
namespace: monitoring
labels:
prometheus: main
spec:
namespaceSelector:
matchNames:
- default
selector:
matchLabels:
app: rails-client
podMetricsEndpoints:
- port: metrics
42 changes: 42 additions & 0 deletions lessons/220/ruby-app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.

# Ignore git directory.
/.git/
/.gitignore

# Ignore bundler config.
/.bundle

# Ignore all environment files (except templates).
/.env*
!/.env*.erb

# Ignore all default key files.
/config/master.key
/config/credentials/*.key

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/.keep

# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/.keep

# Ignore CI service files.
/.github

# Ignore development files
/.devcontainer

# Ignore Docker-related files
/.dockerignore
/Dockerfile*
9 changes: 9 additions & 0 deletions lessons/220/ruby-app/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# See https://git-scm.com/docs/gitattributes for more about git attribute files.

# Mark the database schema as having been generated.
db/schema.rb linguist-generated

# Mark any vendored files as having been vendored.
vendor/* linguist-vendored
config/credentials/*.yml.enc diff=rails_credentials
config/credentials.yml.enc diff=rails_credentials
34 changes: 34 additions & 0 deletions lessons/220/ruby-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# Temporary files generated by your text editor or operating system
# belong in git's global ignore instead:
# `$XDG_CONFIG_HOME/git/ignore` or `~/.config/git/ignore`

# Ignore bundler config.
/.bundle
/.idea

# Ignore all environment files (except templates).
/.env*
!/.env*.erb

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/
!/tmp/pids/.keep

# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/
!/tmp/storage/.keep

# Ignore master key for decrypting credentials and more.
/config/master.key
1 change: 1 addition & 0 deletions lessons/220/ruby-app/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ruby-3.3.5
59 changes: 59 additions & 0 deletions lessons/220/ruby-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# syntax = docker/dockerfile:1

# This Dockerfile is designed for production, not development. Use with Kamal or build'n'run by hand:
# docker build -t ruby-app .
# docker run -d -p 8080:8080 --name ruby-app ruby-app

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=3.3.5
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base

# Rails app lives here
WORKDIR /rails

# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 libpq-dev && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Set production environment
ENV RAKE_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"

# Throw-away build stage to reduce size of final image
FROM base AS build

# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git pkg-config && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git

# Copy application code
COPY . .

# Final stage for app image
FROM base

# Copy built artifacts: gems, application
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
COPY --from=build /rails /rails

# Run and own only the runtime files as a non-root user for security
RUN groupadd --system --gid 1000 rails && \
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
chown -R rails:rails db tmp
USER 1000:1000

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start the server by default, this can be overwritten at runtime
EXPOSE 8080
CMD ["bin/iodine", "-p 8080", "config.ru"]
13 changes: 13 additions & 0 deletions lessons/220/ruby-app/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gem 'connection_pool'
gem 'pg'
gem 'rake'
gem 'standalone_migrations', require: false

gem 'oj'
gem 'prometheus-client'
gem 'rack'
gem 'rage-iodine'
Loading