Skip to content

Commit 49089d7

Browse files
authored
Merge pull request #182 from Librecov/feat/docker-build
feat: docker build
2 parents d87127a + 7511ea0 commit 49089d7

File tree

27 files changed

+519
-252
lines changed

27 files changed

+519
-252
lines changed

.dockerignore

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
1+
.dockerignore
2+
# there are valid reasons to keep the .git, namely so that you can get the
3+
# current commit hash
4+
.git
5+
.log
6+
tmp
7+
8+
# Mix artifacts
19
_build
210
deps
11+
*.ez
12+
releases
13+
14+
# Generate on crash by the VM
15+
erl_crash.dump
16+
17+
# Static artifacts
318
node_modules
4-
.git
5-
.tags
6-
priv/static/js
19+
priv/static

.formatter.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
surface_line_length: 120,
33
import_deps: [:ecto, :phoenix, :surface],
44
inputs: [
5-
"*.{ex,exs}",
5+
"{mix,.formatter}.exs",
66
"priv/*/seeds.exs",
7-
"{config,lib,test}/**/*.{ex,exs}"
7+
"{config,lib,test}/**/*.{ex,exs,sface}",
8+
"lib/librecov_web/live/**/*.{ex,exs,sface}"
89
],
9-
surface_inputs: ["{lib,test}/**/*.{ex,exs,sface}"],
1010
subdirectories: ["priv/*/migrations"],
1111
plugins: [Surface.Formatter.Plugin],
1212
locals_without_parens: [

.github/workflows/ghcr.yml

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
name: CI to GHCR
1+
name: Docker
22

33
on:
4+
pull_request:
45
push:
5-
branches: [ main ]
6+
branches:
7+
- main
8+
tags:
9+
- v*
10+
release:
11+
types: [released]
612

713
env:
814
REGISTRY: ghcr.io
915
IMAGE_NAME: ${{ github.repository }}
1016

1117
jobs:
1218
build-and-push-image:
19+
name: Build
1320
runs-on: ubuntu-latest
1421
permissions:
1522
contents: read
@@ -19,6 +26,17 @@ jobs:
1926
- name: Checkout repository
2027
uses: actions/checkout@v2
2128

29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v1
31+
32+
- name: Cache Docker layers
33+
uses: actions/cache@v2
34+
with:
35+
path: /tmp/.buildx-cache
36+
key: ${{ runner.os }}-buildx-${{ github.sha }}
37+
restore-keys: |
38+
${{ runner.os }}-buildx-
39+
2240
- name: Log in to the Container registry
2341
uses: docker/login-action@5fcefb941de79536616e9422226e33fd39f1706f
2442
with:
@@ -32,10 +50,36 @@ jobs:
3250
with:
3351
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
3452

35-
- name: Build and push Docker image
36-
uses: docker/build-push-action@604f033158cc23bb0aa20cd1742ac95c460d3abf
53+
- name: Docker meta
54+
id: meta
55+
uses: docker/metadata-action@v3
56+
with:
57+
# list of Docker images to use as base name for tags
58+
images: |
59+
ghcr.io/${{ github.repository }}
60+
tags: |
61+
type=schedule
62+
type=semver,pattern={{version}}
63+
type=semver,pattern={{major}}.{{minor}}
64+
type=semver,pattern={{major}}
65+
type=ref,event=branch
66+
type=ref,event=pr
67+
type=ref,event=tag
68+
type=sha,enable=true,priority=100,prefix=sha-,suffix=,format=long
69+
type=edge,branch=main
70+
71+
- name: Build and push
72+
uses: docker/build-push-action@v2
3773
with:
3874
context: .
39-
push: true
75+
push: ${{ github.event_name != 'pull_request' }}
4076
tags: ${{ steps.meta.outputs.tags }}
41-
labels: ${{ steps.meta.outputs.labels }}
77+
labels: ${{ steps.meta.outputs.labels }}
78+
cache-from: type=local,src=/tmp/.buildx-cache
79+
cache-to: type=local,dest=/tmp/.buildx-cache-new
80+
81+
- name: Move cache
82+
shell: bash
83+
run: |
84+
rm -rf /tmp/.buildx-cache
85+
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

.github/workflows/tests.yml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
name: Tests
12
on: push
23

34
jobs:
@@ -7,8 +8,8 @@ jobs:
78
MIX_ENV: test
89
strategy:
910
matrix:
10-
elixir: ["1.12.3"]
11-
otp: ["24.0"]
11+
elixir: ["1.13"]
12+
otp: ["24.1"]
1213
steps:
1314
- name: Cancel previous runs
1415
uses: styfle/cancel-workflow-action@0.9.1
@@ -18,6 +19,7 @@ jobs:
1819
uses: actions/checkout@v2
1920
- name: Sets up an Erlang/OTP environment
2021
uses: erlef/setup-beam@v1
22+
id: beam
2123
with:
2224
elixir-version: ${{ matrix.elixir }}
2325
otp-version: ${{ matrix.otp }}
@@ -29,7 +31,7 @@ jobs:
2931
deps
3032
_build
3133
priv/plts
32-
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('mix.lock') }}-v2
34+
key: ${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('mix.lock') }}-v2
3335
- name: Install dependencies
3436
if: steps.mix-cache.outputs.cache-hit != 'true'
3537
run: |
@@ -48,8 +50,8 @@ jobs:
4850
MIX_ENV: test
4951
strategy:
5052
matrix:
51-
elixir: ["1.12.3"]
52-
otp: ["24.0"]
53+
elixir: ["1.13"]
54+
otp: ["24.1"]
5355
steps:
5456
- name: Cancel previous runs
5557
uses: styfle/cancel-workflow-action@0.9.1
@@ -59,6 +61,7 @@ jobs:
5961
uses: actions/checkout@v2
6062
- name: Sets up an Erlang/OTP environment
6163
uses: erlef/setup-beam@v1
64+
id: beam
6265
with:
6366
elixir-version: ${{ matrix.elixir }}
6467
otp-version: ${{ matrix.otp }}
@@ -70,7 +73,7 @@ jobs:
7073
deps
7174
_build
7275
priv/plts
73-
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('mix.lock') }}-v2
76+
key: ${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('mix.lock') }}-v2
7477
- run: mix format --check-formatted
7578
- run: mix credo
7679
- run: mix dialyzer --no-check --ignore-exit-status
@@ -82,8 +85,8 @@ jobs:
8285
MIX_ENV: test
8386
strategy:
8487
matrix:
85-
elixir: ["1.12.3"]
86-
otp: ["24.0"]
88+
elixir: ["1.13"]
89+
otp: ["24.1"]
8790
services:
8891
db:
8992
image: postgres:13-alpine
@@ -110,6 +113,7 @@ jobs:
110113
- uses: c-hive/gha-yarn-cache@v2
111114
- name: Sets up an Erlang/OTP environment
112115
uses: erlef/setup-beam@v1
116+
id: beam
113117
with:
114118
elixir-version: ${{ matrix.elixir }}
115119
otp-version: ${{ matrix.otp }}
@@ -121,7 +125,7 @@ jobs:
121125
deps
122126
_build
123127
priv/plts
124-
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('mix.lock') }}-v2
128+
key: ${{ runner.os }}-${{ steps.beam.outputs.otp-version }}-${{ steps.beam.outputs.elixir-version }}-${{ hashFiles('mix.lock') }}-v2
125129
- name: Install NPM Packages (Global)
126130
run: yarn install
127131
- name: Seed

.tool-versions

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
elixir 1.12.3-otp-24
2-
erlang 24.1.1
3-
nodejs 14.16.1
1+
elixir 1.13.2-otp-24
2+
erlang 24.1.7
3+
nodejs 16.13.2

Dockerfile

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
1-
FROM elixir:1.13.1-slim AS build
1+
# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian instead of
2+
# Alpine to avoid DNS resolution issues in production.
3+
#
4+
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
5+
# https://hub.docker.com/_/ubuntu?tab=tags
6+
#
7+
#
8+
# This file is based on these images:
9+
#
10+
# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
11+
# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20210902-slim - for the release image
12+
# - https://pkgs.org/ - resource for finding needed packages
13+
# - Ex: hexpm/elixir:1.13.2-erlang-24.1.1-debian-bullseye-20210902-slim
14+
#
15+
ARG BUILDER_IMAGE="hexpm/elixir:1.13.2-erlang-24.1.1-debian-bullseye-20210902-slim"
16+
ARG RUNNER_IMAGE="debian:bullseye-20210902-slim"
17+
18+
FROM ${BUILDER_IMAGE} as builder
219

320
# install build dependencies
4-
RUN apt update && apt install -y build-essential git
21+
RUN apt-get update -y && apt-get install -y build-essential git apt-transport-https curl \
22+
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
23+
24+
# add node deb
25+
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x -o /tmp/setup_node.sh && bash /tmp/setup_node.sh && apt-get install -y nodejs \
26+
&& apt-get clean && rm -f /var/lib/apt/lists/*_* \
27+
&& corepack enable
528

629
# prepare build dir
730
WORKDIR /app
@@ -11,41 +34,68 @@ RUN mix local.hex --force && \
1134
mix local.rebar --force
1235

1336
# set build ENV
14-
ENV MIX_ENV=prod
37+
ENV MIX_ENV="prod"
1538

1639
# install mix dependencies
1740
COPY mix.exs mix.lock ./
18-
COPY config config
19-
RUN mix do deps.get, deps.compile
41+
RUN mix deps.get --only $MIX_ENV
42+
RUN mkdir config
2043

21-
# build assets
22-
# COPY assets/package.json assets/package-lock.json ./assets/
23-
# RUN npm --prefix ./assets ci --progress=false --no-audit --loglevel=error
44+
# copy compile-time config files before we compile dependencies
45+
# to ensure any relevant config change will trigger the dependencies
46+
# to be re-compiled.
47+
COPY config/config.exs config/${MIX_ENV}.exs config/
48+
RUN mix deps.compile
2449

2550
COPY priv priv
26-
# COPY assets assets
27-
# RUN npm run --prefix ./assets deploy
28-
RUN mix phx.digest
2951

30-
# compile and build release
52+
# note: if your project uses a tool like https://purgecss.com/,
53+
# which customizes asset compilation based on what it finds in
54+
# your Elixir templates, you will need to move the asset compilation
55+
# step down so that `lib` is available.
56+
COPY assets assets
57+
ADD openapi.json package.json yarn.lock ./
58+
# compile assets
59+
RUN yarn install --frozen-lockfile
3160
COPY lib lib
32-
COPY openapi.json openapi.json
33-
# uncomment COPY if rel/ exists
34-
# COPY rel rel
35-
RUN mix do compile, release
61+
RUN mix assets.deploy
62+
# Compile the release
3663

37-
# prepare release image
38-
FROM debian:buster AS app
39-
RUN apt update && apt install -y openssl
64+
RUN mix compile
4065

41-
WORKDIR /app
66+
# Changes to config/runtime.exs don't require recompiling the code
67+
COPY config/runtime.exs config/
68+
69+
COPY rel rel
70+
RUN mix release
71+
72+
# start a new build stage so that the final image will only contain
73+
# the compiled release and other runtime necessities
74+
FROM ${RUNNER_IMAGE}
75+
76+
RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales apt-transport-https curl \
77+
&& apt-get clean && rm -f /var/lib/apt/lists/*_*
78+
79+
# add node deb
80+
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x -o /tmp/setup_node.sh && bash /tmp/setup_node.sh && apt-get install -y nodejs --no-install-recommends \
81+
&& apt-get clean && rm -f /var/lib/apt/lists/*_* \
82+
&& corepack enable
83+
84+
# Set the locale
85+
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
4286

43-
# RUN chown nobody:nobody /app
87+
ENV LANG en_US.UTF-8
88+
ENV LANGUAGE en_US:en
89+
ENV LC_ALL en_US.UTF-8
4490

45-
# USER nobody:nobody
91+
WORKDIR "/app"
92+
RUN chown nobody /app
4693

47-
COPY --from=build --chown=nobody:nobody /app/_build/prod/rel/librecov ./
94+
# Only copy the final release from the build stage
95+
COPY --from=builder --chown=nobody:root /app/_build/prod/rel/librecov ./
96+
ADD openapi.json package.json yarn.lock /app/bin/
97+
RUN cd bin && yarn install --production --frozen-lockfile
4898

49-
ENV HOME=/app
99+
USER nobody
50100

51-
CMD ["bin/librecov", "start"]
101+
CMD ["/app/bin/server"]

config/config.exs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use Mix.Config
1+
import Config
22

33
config :librecov, Librecov.Endpoint,
44
url: [host: "localhost"],
@@ -90,7 +90,4 @@ config :kaffy,
9090
admin_logo: "/images/logo.png",
9191
admin_logo_mini: "/images/logo.png"
9292

93-
import_config "#{Mix.env()}.exs"
94-
95-
local_config_path = Path.expand("local.exs", __DIR__)
96-
if File.exists?(local_config_path), do: import_config(local_config_path)
93+
import_config "#{config_env()}.exs"

config/dev.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use Mix.Config
1+
import Config
22

33
# For development, we disable any cache and enable
44
# debugging and code reloading.
@@ -81,3 +81,5 @@ config Librecov.Plug.Github,
8181
secret: "my-secret",
8282
path: "/api/v1/github_webhook",
8383
action: {Librecov.GithubService, :handle}
84+
85+
config :phoenix, :plug_init_mode, :runtime

config/local.sample.exs

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)