Elixir 버전을 사용하고 컨테이너에서 CI/CD 실행

12809 단어 elixirdockerphoenixci
최초는 2020년 12월 24일https://geeks.wego.comhttps://darnahsan.medium.com/working-with-elixir-releases-and-performing-ci-cd-in-containers-383ba03b6768에 발표됐다.
Elixir는 Wego에서 신속하게 도입되었고 주말 프로젝트가 일상적인 구동 요인이 된 후 여러 서비스가 생산에 들어갔다. 왜냐하면 새로운 옵션을 탐색하고 강력한 탄력적인 시스템을 구축하는 운동을 자극했기 때문이다.
컨테이너에서 거의 모든 작업 부하를 실행할 때, 우리는 같은 구축 파이프를 이용하여 컨테이너 이미지를 구축하여 CI/CD를 실행합니다.Elixir는 BEAM에서 운행하는데 열을 재배치하는 등 좋은 특성이 있다. 이것은 용기의 개념과 반대로 용기는 변할 수 없는 이미지이지만 이것은 Elixir가 용기에 대해 우호적이지 않다는 것을 의미하지 않는다.Mix는 Rake for Ruby와 유사한 elixir 구축 도구로, 같은 플랫폼에서 구축된 패키지만 있으면 어디서나 실행할 수 있는 ERTS라는 패키지를 생성하는 것을 지원합니다.이것이 바로 용기가 외부의 의존 없이 그림의 크기를 매우 작게 유지할 수 있는 이유이다.Elixir 버전은 사용하기 쉽지만, 한 버전에 사용할 수 있는 조합이 없기 때문에 이전이나 작업 수행에 필요한 도구 체인을 분리합니다.다음 표는 서로 다른 방법과 그 특징을 나타냈다
Release
Elixir 포럼에 왜 사용해야 하는지에 대한 좋은 게시물이 있기 때문에 왜 버전을 사용해야 하는지 물어볼 수도 있다.예를 들어, 만약 당신이 믹스로 응용 프로그램을 포장하고 믹스 런으로 실행하려고 한다면, 믹스가 부족한 문제를 끊임없이 해결하려면, 그것은 용기 크기에 어떤 영향을 줍니까?1.11.2-erlang-23.1.3 버전의 elixir 이미지는 약 214MB로 다단계 Dockerfile에서 버전을 구축하거나 Mix를 사용하는 프로그램을 실행하는 데 사용됩니다.이에 비해 데비안 이미지는 69.2MB에 불과했다.Phoenix 응용 프로그램에 Elixir 버전을 사용하고 Debian 기반 스테이지로 복사할 때 최종 이미지 크기는 101MB이고 버전을 생성하지 않고 Mix를 사용할 경우 버전 이미지 크기의 6배인 627MB입니다.
Always use Releases



이것은 발행판이 다른 방법에 비해 현저한 장점이 있고 다단계 구축 파일이 이미지 크기에 미치는 영향을 보여 준다.
따라서 우리는 항상 발행판을 사용해야 하는데, 어떻게 해야만 믹스가 잃어버린 기능을 얻을 수 있습니까?이를 위해 Elixir와 Docker 모두 자신의 노력을 다하여 라크를 사용하는 Ruby CI/CD 용기화 프로세스와 유사한 기능을 빈틈없이 실현하였다.실행에 대해 Elixir와 database migration with releases 는 해결 방안이 있습니다. 이 해결 방안에서 당신은 단독 파일을 만들어서 이전을 실행할 수 있습니다. 이것은 표준화된 코드이고 실제로는 EXTO의 일부분이어야 합니다.
defmodule MyApp.Release do
  [@app](http://twitter.com/app) :my_app

def migrate do
    load_app()

for repo <- repos() do
      {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true))
    end
  end

def rollback(repo, version) do
    load_app()
    {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version))
  end

defp repos do
    Application.fetch_env!([@app](http://twitter.com/app), :ecto_repos)
  end

defp load_app do
    Application.load([@app](http://twitter.com/app))
  end
end
발행판을 만든 후, eval을 사용하여 생산 과정에서 이전을 실행할 수 있습니다. 예를 들어
$ _build/prod/rel/my_app/bin/my_app eval "MyApp.Release.migrate"
이전은 특례이다. Ecto는 데이터베이스에 접근해서 이 모든 것을 가능하게 하는 좋은 특성을 가지고 있지만, 생산 환경에서 일부 작업을 실행하려면 별도의 방법이 필요하고, Elixir 응용 프로그램이나 Phoenix에서 구축된 웹 응용 프로그램에 대해 좀 알아야 한다.모든 Elixir 응용 프로그램은 여러 개의 응용 프로그램으로 구성되어 있는데 그 중에서Phoenix 응용 프로그램은 하나의 응용 프로그램 목록이다. 그 중에서 웹과 데이터베이스는 독립된 응용 프로그램이다. 이것은 Elixir 응용 프로그램으로 하여금 건장성을 가지게 하고 어떠한 응용 프로그램도 당신의 전체 서비스를 파괴할 수 없게 한다.이를 위해 elixir 응용 프로그램Ecto Migrator과 기초 지식을 습득하여 응용 프로그램 용기 이미지를 작성하여 임무를 수행하고 응용 프로그램 서비스를 실행할 수 있습니다.Phoenix 애플리케이션 Ghostider를 예로 들겠습니다.우리는 여기서 하위 응용 프로그램과 하위 응용 프로그램을 두 개의 독립된 웹 응용 프로그램 기반으로 나누었다.필요에 따라 우리는 아이들이 환경 변수에서 불러오는 내용을 처리할 수 있고 환경 변수는 운행할 때 용기에 편리하게 전달할 수 있다.
defmodule GhostRider.Application do
  # See [https://hexdocs.pm/elixir/Application.html](https://hexdocs.pm/elixir/Application.html)
  # for more information on OTP Applications
  [@moduledoc](http://twitter.com/moduledoc) false

use Application

def start(_type, _args) do
    base = [
      # Start the Ecto repository
      GhostRider.Repo,
      {Finch, name: GhostRiderFinch}
    ]

web = [
      # Start the Telemetry supervisor
      GhostRiderWeb.Telemetry,
      # Start the PubSub system
      {Phoenix.PubSub, name: GhostRider.PubSub},
      # Start the Endpoint (http/https)
      GhostRiderWeb.Endpoint
      # Start a worker by calling: GhostRider.Worker.start_link(arg)
      # {GhostRider.Worker, arg},
    ]

children =
      case System.get_env("APP_LEVEL") do
        "TASK" -> base
        _ -> base ++ web
      end

# See [https://hexdocs.pm/elixir/Supervisor.html](https://hexdocs.pm/elixir/Supervisor.html)
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: GhostRider.Supervisor]
    Supervisor.start_link(children, opts)
  end

# Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  def config_change(changed, _new, removed) do
    GhostRiderWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end
이 방법은 가능하지만, 프로그램은 발표가 시작될 때만 시작합니다.이 문제를 극복하기 위해서는 eval을 사용하여 실행 작업에 연결된 패키지 함수를 실행해야 하지만, 이 동작을 실행하기 위해서는 응용 프로그램을 시작해야 합니다. all 이(가) 시작되었는지 확인(@app) 및 로드할 하위 레벨 환경 변수를 제어합니다.
elixir release docs 어플리케이션의 모든 하위 항목 로드
애플리케이션에 제한된 하위 객체 로드
마이그레이션과 작업을 정렬하고 컨테이너를 사용할 수 있는 경우 CI/CD 문제는 릴리스에 혼합 버전이 없고 릴리스가 바이트 코드이며 사용할 수 있는 테스트 폴더가 없는 경우 테스트를 어떻게 실행하는가입니다.이것이 바로 docker 다단계 구축의 하이라이트입니다. 우리는 docker compose를 이용하여 구축 과정에서 테스트를 실행하여 우리가 가지고 있는 다양한 기술 창고에서 일치하도록 합니다.
현재, 일부 docker와 docker는 식단을 작성하여, 이것들을 결합시켜 CI/CD 파이프에서 일한다.내가 인정해야 할 점은 용기화 Elixir/Phoenix 응용 프로그램에 자원이 부족하다는 것이다. 지역사회는 이 점을 개선하기 위해 노력해야 한다.다음은 Phoenix 프로그램을 구축하는 데 사용되는 파일입니다. 테스트라는 단계를 볼 수 있습니다. 이것은 docker compose를 사용하는 목표입니다.
# [https://elixirforum.com/t/could-use-some-feedback-on-this-multistage-dockerfile-1st-elixir-phoenix-deployment/30862/10](https://elixirforum.com/t/could-use-some-feedback-on-this-multistage-dockerfile-1st-elixir-phoenix-deployment/30862/10)?

########################
### Dependency stage ###
########################
FROM hexpm/elixir:1.11.2-erlang-23.1.3-debian-buster-20201012 AS base

# install build dependencies
RUN apt-get -qq update && \
    apt-get -qq -y install build-essential npm git python --fix-missing --no-install-recommends

# prepare build dir
WORKDIR /app

ARG MIX_ENV
ARG RELEASE_ENV

ENV LANG=C.UTF-8 LC_ALL=C.UTF-8

# Update timezone
ENV TZ=Asia/Singapore

# install hex + rebar
RUN mix local.hex --force && \
    mix local.rebar --force

# set build ENV
ENV MIX_ENV=${MIX_ENV}
ENV RELEASE_ENV=${RELEASE_ENV}

COPY mix.exs mix.lock ./
COPY config config

# install mix dependencies
RUN mix deps.get --only ${MIX_ENV}
RUN mix deps.compile

COPY lib ./lib
COPY priv ./priv
#########################
####### Test Stage ######
#########################

FROM base as tester
WORKDIR /app
COPY test test

########################
# Build Phoenix assets #
########################
# Using stretch for now because it includes Python
# Otherwise you get errors, could use a smaller image though
FROM node:14.15.3-stretch AS assets
WORKDIR /app

COPY --from=base /app/deps /app/deps/
COPY assets/package.json assets/package-lock.json ./assets/
RUN npm --prefix ./assets ci --progress=false --no-audit --loglevel=error

COPY lib ./lib
COPY priv ./priv
COPY assets/ ./assets/

RUN npm run --prefix ./assets deploy

#########################
# Create Phoenix digest #
#########################
FROM base AS digest
WORKDIR /app

# set build ENV
ENV MIX_ENV=${MIX_ENV}
ENV RELEASE_ENV=${RELEASE_ENV}

COPY --from=assets /app/priv ./priv
RUN mix phx.digest

#######################
#### Create release ###
#######################
FROM digest AS release
WORKDIR /app

ARG MIX_ENV
ARG RELEASE_ENV
ENV MIX_ENV=${MIX_ENV}
ENV RELEASE_ENV=${RELEASE_ENV}

COPY --from=digest /app/priv/static ./priv/static

RUN mix do compile, release

#################################################
# Create the actual image that will be deployed #
#################################################
FROM debian:buster-slim AS deploy

# Install stable dependencies that don't change often
RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  apt-utils \
  openssl \
  curl \
  wget && \
  rm -rf /var/lib/apt/lists/*

# Set WORKDIR after setting user to nobody so it automatically gets the right permissions
# When the app starts it will need to be able to create a tmp directory in /app
WORKDIR /app

ARG MIX_ENV
ARG RELEASE_ENV

ENV MIX_ENV=${MIX_ENV}
ENV RELEASE_ENV=${RELEASE_ENV}

ENV LANG=C.UTF-8 LC_ALL=C.UTF-8

# Update timezone
ENV TZ=Asia/Singapore

HEALTHCHECK --start-period=10s \
  --interval=15s \
  --timeout=5s \
  --retries=3 \
  CMD curl -sSf [http://localhost:8080/heartbeat](http://localhost:8080/heartbeat) || exit 1

COPY --from=release /app/_build/${MIX_ENV}/rel/ghost_rider ./

ENV HOME=/app
# Exposes port to the host machine
EXPOSE 8080

CMD ["bin/ghost_rider", "start"]
프로그램을 실행하는 표준 docker compose 파일은 Postgres 데이터베이스를 시작하고 프로그램을 시작합니다.
version: "3.7"
services:
  ghost-rider:
    build:
      context: .
      args:
        MIX_ENV: "${MIX_ENV}"
        RELEASE_ENV: "${RELEASE_ENV}"
    image: wego/ghost-rider
    depends_on:
      - ghost-rider-db
    restart: on-failure
    ports:
      - "8080:8080"
    environment:
      MIX_ENV: "${MIX_ENV}"
      RELEASE_ENV: "${RELEASE_ENV}"
      PORT: "8080"
      SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
      DB_NAME: ghost-rider
      DB_PASSWORD: ghost-rider
      DB_HOST: ghost-rider-db
      APP_LEVEL: WEB

ghost-rider-db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: ghost-rider
      POSTGRES_DB: "${POSTGRES_DB}"
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - "postgresql-data:/var/lib/postgresql/data"

volumes:
  postgresql-data:
컨테이너 이미지를 구축하고 실행하려면
$ docker-compose -f docker-compose.yml up -d
마이그레이션 실행
$ docker-compose run --rm ghost-rider bin/ghost_rider eval "Release.migrate"
테스트를 실행하려면 기본값을 덮어쓰고 실행할 대상을 정의하기 위해 다른 docker compose 파일을 만들어야 합니다.필요한 경우 새 파일을 만들 수도 있습니다.
version: "3.7"
services:
  ghost-rider:
    build:
      target: tester
      args:
        - MIX_ENV=test
        - RELEASE_ENV=test
    image: wego/ghost-rider-test
    ports:
      - "8080:8080"
    environment:
      - MIX_ENV=test
      - RELEASE_ENV=test
      - DB_NAME=ghost-rider-test
      - DB_PASSWORD=ghost-rider
      - DB_HOST=ghost-rider-db
그것 으로 당신 은 테스트 데이터베이스 를 설정하고 테스트 를 실행할 수 있으며, 아래 조작 만 수행할 수 있다
$ docker-compose -f docker-compose.yml -f docker-compose.test.yml run --rm ghost-rider mix ecto.setup

$ docker-compose -f docker-compose.yml -f docker-compose.test.yml run --rm ghost-rider mix test
Elixir에 대한 이해가 필요할 뿐입니다. 다른 언어와 마찬가지로 Docker 도구와 함께 사용하면 이미지를 구축하고 CI/CD를 실행할 수 있으며 마찰이 생기지 않습니다.
나는 이것이 Docker와 용기와 함께 놀라운 기술로 일을 매우 간단하게 하고 CI/CD에 파이프를 구축하는 데 도움이 되기를 바란다.

좋은 웹페이지 즐겨찾기