diff --git a/.dockerignore b/.dockerignore index 61a7393..e255381 100644 --- a/.dockerignore +++ b/.dockerignore @@ -27,6 +27,7 @@ # Common development/test artifacts /cover/ /doc/ +/docs/ /test/ /tmp/ .elixir_ls diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4233517..6a9765b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,9 +56,13 @@ jobs: build-image: - name: Build container image + name: Build ${{ matrix.env }} container image runs-on: ubuntu-latest + strategy: + matrix: + env: [prod, ce] + steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx @@ -67,11 +71,13 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.env }} - name: Build uses: docker/build-push-action@v6 with: context: . push: false + build-args: | + MIX_ENV=${{ matrix.env }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/publish-containers.yml b/.github/workflows/publish-containers.yml new file mode 100644 index 0000000..3e43e19 --- /dev/null +++ b/.github/workflows/publish-containers.yml @@ -0,0 +1,43 @@ +name: Publish Container Images + +on: + push: + branches: [main] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + push-image: + + name: Build and publish ${{ matrix.env }} container image + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + strategy: + matrix: + env: [prod, ce] + + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.env }} + - name: Build + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + build-args: | + MIX_ENV=${{ matrix.env }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index 9296ae2..83c5d6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,13 +11,14 @@ WORKDIR /app RUN mix local.hex --force && \ mix local.rebar --force -# download Supabase SSL ca-certificate -RUN curl -L https://supabase-downloads.s3-ap-southeast-1.amazonaws.com/prod/ssl/prod-ca-2021.crt -o prod-ca-2021.crt - # set build ENV -ENV MIX_ENV="prod" +ARG MIX_ENV="ce" ENV ERL_FLAGS="+JPperf true" +# Download Supabase TLS ca-certificate +RUN mkdir certs \ + && if [ "${MIX_ENV}" = "prod" ]; then curl -L https://supabase-downloads.s3-ap-southeast-1.amazonaws.com/prod/ssl/prod-ca-2021.crt -o certs/prod-ca-2021.crt; fi + # install mix dependencies COPY mix.exs mix.lock ./ RUN mix deps.get --only $MIX_ENV @@ -32,6 +33,7 @@ RUN mix deps.compile COPY priv priv COPY lib lib +COPY ee ./ee COPY assets assets @@ -51,6 +53,10 @@ RUN mix release # the compiled release and other runtime necessities FROM ubuntu:noble-20240827.1 +# set runner ENV +ARG MIX_ENV="ce" +ENV MIX_ENV=${MIX_ENV} + RUN apt-get update -y && \ apt-get install -y libstdc++6 openssl libncurses6 locales ca-certificates \ && apt-get clean && rm -f /var/lib/apt/lists/*_* @@ -65,11 +71,8 @@ ENV LC_ALL=en_US.UTF-8 WORKDIR "/app" RUN chown nobody /app -# set runner ENV -ENV MIX_ENV="prod" - # Only copy the final release from the build stage -COPY --from=builder --chown=nobody:root /app/prod-ca-2021.crt ./ +COPY --from=builder --chown=nobody:root /app/certs ./ COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/cozycoder ./ USER nobody diff --git a/config/ce.exs b/config/ce.exs new file mode 100644 index 0000000..ac373fe --- /dev/null +++ b/config/ce.exs @@ -0,0 +1,20 @@ +import Config + +# Note we also include the path to a cache manifest +# containing the digested version of static files. This +# manifest is generated by the `mix assets.deploy` task, +# which you should run after static files are built and +# before starting your production server. +config :cozycoder, CozyCoderWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json" + +# Configures Swoosh API Client +config :swoosh, api_client: Swoosh.ApiClient.Finch, finch_name: CozyCoder.Finch + +# Disable Swoosh Local Memory Storage +config :swoosh, local: false + +# Do not print debug messages in production +config :logger, level: :info + +# Runtime production configuration, including reading +# of environment variables, is done on config/runtime.exs. diff --git a/config/prod.exs b/config/prod.exs index ac373fe..644bae9 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -1,5 +1,8 @@ import Config +# Use Supabase TLS certificate for database connections. +config :cozycoder, CozyCoder.Repo, ssl: [cacertfile: "/app/prod-ca-2021.crt"] + # Note we also include the path to a cache manifest # containing the digested version of static files. This # manifest is generated by the `mix assets.deploy` task, diff --git a/config/runtime.exs b/config/runtime.exs index 90f194d..972e6c0 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -31,8 +31,7 @@ if config_env() == :prod do maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: [] config :cozycoder, CozyCoder.Repo, - # Use Supabase TLS certificate - ssl: [cacertfile: "/app/prod-ca-2021.crt"], + # ssl: true, url: database_url, pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), socket_options: maybe_ipv6 diff --git a/fly.toml b/fly.toml index ee4eda1..f9eb8ee 100644 --- a/fly.toml +++ b/fly.toml @@ -9,6 +9,9 @@ kill_signal = 'SIGTERM' [build] +[build.args] +MIX_ENV = "prod" + [deploy] release_command = '/app/bin/migrate' diff --git a/mix.exs b/mix.exs index 61faa11..86a0e59 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,7 @@ defmodule CozyCoder.MixProject do version: "0.1.0", elixir: "~> 1.17", elixirc_paths: elixirc_paths(Mix.env()), - start_permanent: Mix.env() == :prod, + start_permanent: Mix.env() in [:prod, :ce], aliases: aliases(), deps: deps() ] @@ -24,8 +24,9 @@ defmodule CozyCoder.MixProject do end # Specifies which paths to compile per environment. - defp elixirc_paths(:test), do: ["lib", "test/support"] - defp elixirc_paths(_), do: ["lib"] + defp elixirc_paths(:test), do: ["lib", "test/support", "ee/lib"] + defp elixirc_paths(:ce), do: ["lib"] + defp elixirc_paths(_), do: ["lib", "ee/lib"] # Specifies your project dependencies. #