-
Notifications
You must be signed in to change notification settings - Fork 42
/
Makefile
154 lines (136 loc) · 5.99 KB
/
Makefile
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
.PHONY: env over build up exec down run ls start
.PHONY: check vs install-compose pre-commit pyre-apply
# Convenience `make` recipes for Docker Compose.
# See URL below for documentation on Docker Compose.
# https://docs.docker.com/engine/reference/commandline/compose
# **Change `SERVICE` to specify other services and projects.**
# Note that variables defined in the host shell are ignored if the
# `.env` file also defines those variables due to the current logic.
SERVICE = train
COMMAND = /usr/bin/zsh --login
# `PROJECT` is equivalent to `COMPOSE_PROJECT_NAME`.
# Project names are made unique for each user to prevent name clashes,
# which may cause issues if multiple users are using the same account.
# Specify `PROJECT` for the `make` command if this is the case.
_PROJECT = "${SERVICE}-${USR}"
_TIMESTAMP = $(shell date +"%Y%m%d-%H%M%S")
# The `COMPOSE_PROJECT_NAME` variable must be lowercase.
PROJECT = $(shell echo ${_PROJECT} | tr "[:upper:]" "[:lower:]")-${_TIMESTAMP}
PROJECT_ROOT = /opt/project
# Creates a `.env` file in ${PWD} if it does not exist.
# This will help prevent UID/GID bugs in `docker-compose.yaml`,
# which unfortunately cannot use shell outputs in the file.
# Image names have the usernames appended to them to prevent
# name collisions between different users.
# The timezone is Asia/Seoul by default because I live here.
TZ ?= Asia/Seoul
GID = $(shell id -g)
UID = $(shell id -u)
GRP = $(shell id -gn)
USR = $(shell id -un)
REPOSITORY = cresset
TAG = "${SERVICE}-${USR}"
_IMAGE_NAME = "${REPOSITORY}:${TAG}-${_TIMESTAMP}"
# Image names are made lowercase even though Docker can
# recognize uppercase for cross-platform compatibility.
IMAGE_NAME = $(shell echo ${_IMAGE_NAME} | tr "[:upper:]" "[:lower:]")
# Makefiles require `$\` at the end of a line for multi-line string values.
# https://www.gnu.org/software/make/manual/html_node/Splitting-Lines.html
ENV_TEXT = "$\
\# When using the \`root\` user with \`UID=0\`/\`USR=root\`, set \`ADD_USER=exclude\`.\n$\
GID=${GID}\n$\
UID=${UID}\n$\
GRP=${GRP}\n$\
USR=${USR}\n$\
HOST_ROOT=.\n$\
SERVICE=${SERVICE}\n$\
\# Do not use the same \`PROJECT\` name for different projects on the same host!\n$\
PROJECT=${PROJECT}\n$\
PROJECT_ROOT=${PROJECT_ROOT}\n$\
IMAGE_NAME=${IMAGE_NAME}\n$\
COMMAND=${COMMAND}\n$\
TZ=${TZ}\n$\
"
# The `.env` file must be checked via shell as is cannot be a Makefile target.
# Doing so would make it impossible to reference `.env` in the `-include` command.
env: # Creates the `.env` file if it does not exist.
@if [ -f ${ENV_FILE} ]; then echo "\`${ENV_FILE}\` already exists!"; \
else printf ${ENV_TEXT} >> ${ENV_FILE}; fi
check: # Checks if the `.env` file exists.
@if [ ! -f "${ENV_FILE}" ]; then \
printf "File \`${ENV_FILE}\` does not exist. " && \
printf "Run \`make env\` to create \`${ENV_FILE}\`.\n" && \
exit 1; \
fi
# Creates VSCode server directory to prevent Docker Compose
# from creating the directory with `root` ownership.
VSCODE_SERVER_PATH = ${HOME}/.vscode-server
vs:
@mkdir -p ${VSCODE_SERVER_PATH}
OVERRIDE_FILE = docker-compose.override.yaml
# The newline symbol is placed at the start of the line because
# Makefiles do not read the initial spaces otherwise.
# The user's $HOME directory on the host should not be mounted on the
# container's $HOME directory as this would override the configurations
# inside the container with those from the host.
# The home directory is therefore mounted in a separate directory,
# which also serves as an example of how to make volume pairings.
OVERRIDE_BASE = "$\
services:$\
\n ${SERVICE}:$\
\n volumes:$\
\n - $$"{HOME}":/mnt/home$\
\n"
# Create override file for Docker Compose configurations for each user.
# For example, different users may use different host volume directories.
${OVERRIDE_FILE}:
printf ${OVERRIDE_BASE} >> ${OVERRIDE_FILE}
# Cannot use `override` as a recipe name as it is a `make` keyword.
over: ${OVERRIDE_FILE}
# Optionally read variables from the environment file if it exists.
# This line must be placed after all other variable definitions to allow
# variables in the `${ENV_FILE}` to be overridden by user-defined values.
ENV_FILE = .env
-include ${ENV_FILE}
build: check vs # Rebuild the image before creating a new container.
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 \
docker compose -p ${PROJECT} up --build -d ${SERVICE}
build-only: check # Build the image without creating a new container.
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 \
docker compose -p ${PROJECT} build ${SERVICE}
up: check vs # Start service. Creates a new container from the image.
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 \
docker compose -p ${PROJECT} up -d ${SERVICE}
exec: # Execute service. Enter interactive shell.
DOCKER_BUILDKIT=1 \
docker compose -p ${PROJECT} exec ${SERVICE} ${COMMAND}
# Useful if the previous container must not be deleted.
start: # Start a stopped service without recreating the container.
docker compose -p ${PROJECT} start ${SERVICE}
down: # Shut down the service and delete containers, volumes, networks, etc.
docker compose -p ${PROJECT} down
run: check vs # Used for debugging cases where the service will not start.
docker compose -p ${PROJECT} run --rm ${SERVICE} ${COMMAND}
ls: # List all services.
docker compose ls -a
# Utility for installing Docker Compose on Linux (but not WSL) systems.
# Visit https://docs.docker.com/compose/install for the full documentation.
COMPOSE_VERSION = v2.29.1
COMPOSE_OS_ARCH = linux-x86_64
COMPOSE_URL = https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-${COMPOSE_OS_ARCH}
COMPOSE_PATH = ${HOME}/.docker/cli-plugins
COMPOSE_FILE = ${COMPOSE_PATH}/docker-compose
${COMPOSE_FILE}:
mkdir -p "${COMPOSE_PATH}"
curl -fksSL "${COMPOSE_URL}" -o "${COMPOSE_FILE}"
chmod +x "${COMPOSE_FILE}"
install-compose: ${COMPOSE_FILE}
pre-commit:
pre-commit run --all-files
PYRE_CONFIGURATION = .pyre_configuration
${PYRE_CONFIGURATION}:
pyre init
# Perform static analysis on the codebase and
# apply the annotations to the code in-place.
pyre-apply: ${PYRE_CONFIGURATION}
pyre infer -i