In software engineering, continuous integration (CI) is the practice of merging all developers' working copies to a shared mainline several times a day. Grady Booch first proposed the term CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.
source: wikipedia
build_steps: &build_steps
  working_directory: ~/repo
  steps:
    - checkout
    - run: bundle install
    - run: bundle exec rake
version: 2
jobs:
  test_ruby-2.7:
    <<: *build_steps
    docker:
      - image: circleci/ruby:2.7
  test_ruby-3.0:
    <<: *build_steps
    docker:
      - image: circleci/ruby:3.0
workflows:
  version: 2
  test_and_release:
    jobs:
      - test_ruby-2.7
      - test_ruby-3.0name: Rails
on:
  push:
jobs:
  build:
    name: Build & test
    runs-on: ubuntu-latest
    services:
      posgres:
        image: postgres:12
    steps:
      - uses: actions/checkout@v2
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          bundler-cache: false
      - name: Install dependencies
        run: |
          gem install bundler
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3
      - name: Setup test database
        env:
          RAILS_ENV: test
        run: bundle exec rake db:drop db:create db:migrate
      - name: Run tests
        env:
          RAILS_ENV: test
        run: bundle exec rspec
      - name: Run linter
        run: bundle exec rubocop -c .rubocop.yml
OS-level virtualization is an operating system paradigm in which the kernel allows the existence of multiple isolated user space instances. Such instances, called containers (LXC, Solaris containers, Docker), Zones (Solaris containers), virtual private servers (OpenVZ), partitions, virtual environments (VEs), virtual kernels (DragonFly BSD), or jails (FreeBSD jail or chroot jail), may look like real computers from the point of view of programs running in them. A computer program running on an ordinary operating system can see all resources (connected devices, files and folders, network shares, CPU power, quantifiable hardware capabilities) of that computer. However, programs running inside of a container can only see the container's contents and devices assigned to the container.
Source: wikipedia
Vagrant.configure("2") do |config|
  config.vm.define "ops01" do |ops|
    ops.vm.box = "bento/centos-7.2"
    ops.vm.network "forwarded_port", guest: 22, host: 2222, id: "ssh"
    ops.vm.network "private_network", ip: "10.1.0.22"
    ops.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "256"
    end
  end
  config.vm.define "ops02" do |ops|
    ops.vm.box = "bento/centos-7.2"
    ops.vm.network "forwarded_port", guest: 22, host: 2223, id: "ssh"
    ops.vm.network "private_network", ip: "10.1.0.23"
    ops.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.memory = "256"
    end
  end
endFROM ruby:3.0.1-alpine3.12
RUN apk add --no-cache build-base=0.5-r2\
                       postgresql=12.7-r0\
                       postgresql-dev=12.7-r0\
                       git=2.26.3-r0\
                       shared-mime-info=1.15-r0
RUN mkdir -p /srv/www/app
WORKDIR /srv/www/app
ENV RAILS_LOG_TO_STDOUT 1
ENV RAILS_ENV production
RUN bundle config set deployment 'true' && bundle config set without 'development test'
# gem caching
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install --jobs=3 --retry=3
# copy app
COPY app ./app
COPY bin ./bin
COPY config ./config
COPY config.ru Procfile Rakefile ./
COPY db ./db
COPY lib ./lib
COPY vendor ./vendor
EXPOSE 3000
CMD ["bundle", "exec", "rails", "server"]# https://docs.docker.com/engine/reference/commandline/build/
$ docker build . -t railsapp
# https://docs.docker.com/engine/reference/run/
$ docker run -it --rm --name railsapp railsapp
# https://docs.docker.com/engine/reference/commandline/exec/
$ docker exec railsapp db:create db:migrateversion: "3.1"
services:
  psql:
    container_name: tc-psql
    image: postgres:9.6.3
    restart: always
    ports:
      - 7121:5432
  redis:
    container_name: tc-redis
    image: redis:4
    restart: always
    ports:
      - 7122:6379
  mailcatcher:
    container_name: tc-mailcatcher
    image: schickling/mailcatcher
    restart: always
    ports:
      - 7125:1025
      - 7180:108$ docker-compose up