-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDockerfile
118 lines (86 loc) · 3.62 KB
/
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
FROM clojure:temurin-17-alpine AS builder
# Create directory for project code (working directory)
RUN mkdir -p /build
# Set Docker working directory
WORKDIR /build
# Cache and install Clojure dependencies
# Add before copying code to cache the layer even if code changes
COPY deps.edn Makefile shadow-cljs.edn package.json /build/
RUN make deps
# Copy project to working directory
# .dockerignore file excludes all but essential files
COPY ./ /build
RUN apk add --no-cache nodejs npm
RUN npm install
# `dist` task packages Clojure service as an uberjar
# - creates: /build/practicalli-gameboard-api-service.jar
# - uses command `clojure -T:build uberjar`
RUN make dist
# End of Docker builder image
# ------------------------------------------
# ------------------------------------------
# Docker container to run Practicalli Gameboard API Service
# run locally using: docker-compose up --build
# ------------------------
# Setup Run-time Container
# Official OpenJDK Image
FROM eclipse-temurin:17-alpine
# Example labels for runtime docker image
# LABEL org.opencontainers.image.authors="[email protected]"
# LABEL net.clojars.tools.ifs.parts="tools ifs parts service"
# LABEL version="0.1.0-SNAPSHOT"
# LABEL description="parts.ifs.tools service"
# Add operating system packages
# - dumb-init to ensure SIGTERM sent to java process running Clojure service
# - Curl and jq binaries for manual running of system integration scripts
# check for newer package versions: https://pkgs.alpinelinux.org/
RUN apk add --no-cache \
dumb-init~=1.2.5 \
curl~=8.11 \
jq~=1.7
# Create Non-root group and user to run service securely
RUN addgroup -g 1001 clojure && adduser -u 1001 -S clojure -G clojure
# Create directory to contain service archive, owned by non-root user
RUN mkdir -p /app && chown -R clojure. /app
# Tell docker that all future commands should run as the appuser user
USER clojure
# Copy service archive file from Builder image
WORKDIR /app
COPY --from=builder /build/target/parts-standalone.jar /app/
# Optional: Add System Integration testing scripts
# RUN mkdir -p /app/test-scripts
# COPY --from=builder /build/test-scripts/curl--* /app/test-scripts/
# ------------------------
# Set Service Environment variables
# optional over-rides for Integrant configuration
# ENV HTTP_SERVER_PORT=
# ENV MYSQL_DATABASE=
ENV SERVICE_PROFILE=prod
# Expose port of HTTP Server
EXPOSE 3000
# ------------------------
# Run service
# Docker Service heathcheck
# docker inspect --format='{{json .State.Health}}' container-name
# - local heathcheck defined in `compose.yaml` service definition
# Heathchck options:
# --interval=30s --timeout=30s --start-period=10s --retries=3
# Shell:
# HEALTHCHECK \
# CMD curl --fail http://localhost:8080/system-admin/status || exit 1
# Exec array:
HEALTHCHECK \
CMD ["curl", "--fail", "http://localhost:3000/up"]
# JDK_JAVA_OPTIONS environment variable for setting JVM options
# Use JVM options that optomise running in a container
# For very low latency, use the Z Garbage collector "-XX:+UseZGC"
ENV JDK_JAVA_OPTIONS="-XshowSettings:system -XX:+UseContainerSupport -XX:MaxRAMPercentage=90"
# Start service using dumb-init and java run-time
# (overrides `jshell` entrypoint - default in eclipse-temuring image)
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["java", "-jar", "/app/parts-standalone.jar"]
# Docker Entrypoint documentation
# https://docs.docker.com/engine/reference/builder/#entrypoint
# $kill PID For Graceful Shutdown(SIGTERM) - can be caught for graceful shutdown
# $kill -9 PID For Forceful Shutdown(SIGKILL) - process ends immeciately
# SIGSTOP cannot be intercepted, process ends immediately