diff --git a/ansible/roles/hosts/templates/Makefile.j2 b/ansible/roles/hosts/templates/Makefile.j2 index fa3d296..48cfad5 100644 --- a/ansible/roles/hosts/templates/Makefile.j2 +++ b/ansible/roles/hosts/templates/Makefile.j2 @@ -1,5 +1,5 @@ CMDS := exec -SERVICE ?= cli +SERVICE ?= myos -include /etc/default/myos ansible: @@ -12,16 +12,16 @@ ansible-pull: @$(if $(ANSIBLE_CONFIG),ANSIBLE_CONFIG=$(ANSIBLE_GIT_DIRECTORY)/$(ANSIBLE_CONFIG)) ansible-pull --url $(ANSIBLE_GIT_REPOSITORY) $(if $(ANSIBLE_GIT_KEY_FILE),--key-file $(ANSIBLE_GIT_KEY_FILE)) $(if $(ANSIBLE_GIT_VERSION),--checkout $(ANSIBLE_GIT_VERSION)) $(if $(ANSIBLE_GIT_DIRECTORY),--directory $(ANSIBLE_GIT_DIRECTORY)) $(if $(ANSIBLE_TAGS),--tags $(ANSIBLE_TAGS)) $(if $(ANSIBLE_EXTRA_VARS),--extra-vars '$(ANSIBLE_EXTRA_VARS)') $(if $(findstring true,$(FORCE)),--force) $(if $(findstring true,$(DRYRUN)),--check) --full $(if $(ANSIBLE_INVENTORY),--inventory $(ANSIBLE_INVENTORY)) $(ANSIBLE_VERBOSE) $(ANSIBLE_PLAYBOOK) exec: - @make -C $(ANSIBLE_GIT_DIRECTORY) exec ARGS='$(ARGS)' DOCKER_NAME=$(COMPOSE_PROJECT_NAME)_$(SERVICE) ENV=$(ENV) DOCKER_RUN_WORKDIR= + @make -C $(ANSIBLE_GIT_DIRECTORY) exec ARGS='$(ARGS)' DOCKER_NAME=$(COMPOSE_PROJECT_NAME)-$(SERVICE) ENV=$(ENV) DOCKER_RUN_WORKDIR= connect: - @docker exec -it $(COMPOSE_PROJECT_NAME)_$(SERVICE) /bin/bash || true + @docker exec -it $(COMPOSE_PROJECT_NAME)-$(SERVICE) /bin/bash || true logs: - @docker logs --follow --tail 100 $(COMPOSE_PROJECT_NAME)_$(SERVICE) || true + @docker logs --follow --tail 100 $(COMPOSE_PROJECT_NAME)-$(SERVICE) || true logs-nofollow: - @docker logs --tail 100 $(COMPOSE_PROJECT_NAME)_$(SERVICE) || true + @docker logs --tail 100 $(COMPOSE_PROJECT_NAME)-$(SERVICE) || true run: @$(ARGS) diff --git a/aws/def.aws.mk b/aws/def.aws.mk index b12ac7a..a248060 100644 --- a/aws/def.aws.mk +++ b/aws/def.aws.mk @@ -1,16 +1,18 @@ AWS_ACCESS_KEY_ID := $(if $(AWS_CREDENTIALS),$(shell $(call conf,$(AWS_CREDENTIALS),$(or $(AWS_PROFILE),default),aws_access_key_id))) -AWS_AMI_DESCRIPTION ?= $(SERVICE_VERSION) -AWS_AMI_NAME ?= $(SERVICE_NAME)-$(AWS_S3_FILENAME) +AWS_AMI_DESCRIPTION ?= $(AWS_SERVICE_VERSION) +AWS_AMI_NAME ?= $(AWS_SERVICE_NAME)-$(AWS_S3_FILENAME) AWS_CREDENTIALS ?= $(wildcard $(HOME)/.aws/credentials) AWS_DEFAULT_REGION ?= eu-west-1 AWS_DEFAULT_OUTPUT ?= text AWS_INSTANCE_ID ?= $(shell timeout 0.1 curl -s http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null) AWS_VM_IMPORT_ROLE_NAME ?= vmimport -AWS_S3_BUCKET ?= $(SERVICE_NAME) +AWS_S3_BUCKET ?= $(AWS_SERVICE_NAME) AWS_S3_FILENAME ?= $(PACKER_ISO_NAME) AWS_S3_KEY ?= $(PACKER_ISO_FILE) AWS_SECRET_ACCESS_KEY := $(if $(AWS_CREDENTIALS),$(shell $(call conf,$(AWS_CREDENTIALS),$(or $(AWS_PROFILE),default),aws_secret_access_key))) -AWS_SNAP_DESCRIPTION ?= $(SERVICE_NAME)-$(SERVICE_VERSION)-$(AWS_S3_FILENAME) +AWS_SERVICE_NAME ?= $(COMPOSE_SERVICE_NAME) +AWS_SERVICE_VERSION ?= $(BUILD_DATE)-$(VERSION) +AWS_SNAP_DESCRIPTION ?= $(AWS_SERVICE_NAME)-$(AWS_SERVICE_VERSION)-$(AWS_S3_FILENAME) CMDS += aws DOCKER_RUN_VOLUME += -v $(HOME)/.aws:/home/$(USER)/.aws ENV_VARS += AWS_ACCESS_KEY_ID AWS_AMI_DESCRIPTION AWS_AMI_NAME AWS_DEFAULT_OUTPUT AWS_DEFAULT_REGION AWS_INSTANCE_ID AWS_PROFILE AWS_S3_BUCKET AWS_S3_KEY AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_SNAP_DESCRIPTION AWS_SNAP_ID diff --git a/make/apps/def.docker.mk b/make/apps/def.docker.mk index dcca1fc..cf958fb 100644 --- a/make/apps/def.docker.mk +++ b/make/apps/def.docker.mk @@ -3,6 +3,7 @@ COMPOSE_ARGS ?= --ansi auto COMPOSE_FILE ?= $(wildcard docker-compose.yml docker/docker-compose.yml $(foreach file,$(patsubst docker/docker-compose.%,%,$(basename $(wildcard docker/docker-compose.*.yml))),$(if $(filter true,$(COMPOSE_FILE_$(file)) $(COMPOSE_FILE_$(call UPPERCASE,$(file)))),docker/docker-compose.$(file).yml))) COMPOSE_FILE_$(ENV) ?= true COMPOSE_FILE_DEBUG ?= $(if $(DEBUG),true) +COMPOSE_FILE_MYOS ?= true COMPOSE_FILE_NFS ?= $(MOUNT_NFS) COMPOSE_FILE_SSH ?= true ifneq ($(SUBREPO),) @@ -11,7 +12,7 @@ else COMPOSE_FILE_APP ?= true endif COMPOSE_IGNORE_ORPHANS ?= false -COMPOSE_PROJECT_NAME ?= $(USER)-$(APP)-$(ENV)$(addprefix -,$(subst /,,$(subst -,,$(APP_PATH)))) +COMPOSE_PROJECT_NAME ?= $(subst .,,$(call LOWERCASE,$(USER)-$(APP_NAME)-$(ENV)$(addprefix -,$(subst /,,$(subst -,,$(APP_PATH)))))) COMPOSE_SERVICE_NAME ?= $(subst _,-,$(COMPOSE_PROJECT_NAME)) COMPOSE_VERSION ?= 2.5.0 CONTEXT += COMPOSE_FILE DOCKER_REPOSITORY @@ -57,6 +58,26 @@ DOCKER_COMPOSE_DOWN_OPTIONS := --rmi all -v DOCKER_COMPOSE_UP_OPTIONS := -d --build endif +# function docker-build: Build docker image +define docker-build + $(call INFO,docker-build,$(1)$(comma) $(2)$(comma) $(3)) + $(eval path := $(patsubst %/,%,$(1))) + $(eval service := $(subst .,,$(call LOWERCASE,$(lastword $(subst /, ,$(path)))))) + $(eval tag := $(or $(2),$(DOCKER_REPOSITORY)/$(service):$(DOCKER_IMAGE_TAG))) + $(eval target := $(subst ",,$(subst ',,$(or $(3),$(DOCKER_BUILD_TARGET))))) + $(eval image_id := $(shell docker images -q $(tag) 2>/dev/null)) + $(eval build_image := $(or $(filter false,$(DOCKER_BUILD_CACHE)),$(if $(image_id),,true))) + $(if $(build_image),$(RUN) docker build $(DOCKER_BUILD_ARGS) --build-arg DOCKER_BUILD_DIR="$(path)" $(DOCKER_BUILD_LABEL) --tag $(tag) $(if $(target),--target $(target)) -f $(path)/Dockerfile $(or $(DOCKER_BUILD_DIR),.),$(call INFO,docker image $(tag) has id $(image_id))) +endef +# function docker-commit: Commit docker image +define docker-commit + $(call INFO,docker-commit,$(1)$(comma) $(2)$(comma) $(3)$(comma) $(4)) + $(eval service := $(or $(1),$(DOCKER_SERVICE))) + $(eval container := $(or $(2),$(firstword $(shell $(call docker-compose,ps -q $(service) 2>/dev/null))))) + $(eval repository := $(or $(3),$(DOCKER_REPOSITORY)/$(service))) + $(eval tag := $(or $(4),$(DOCKER_IMAGE_TAG))) + $(RUN) docker commit $(container) $(repository):$(tag) +endef # function docker-compose: Run docker-compose with arg 1 define docker-compose $(call INFO,docker-compose,$(1)) @@ -69,32 +90,12 @@ define docker-compose-exec-sh $(if $(DOCKER_RUN),$(call docker-build,$(MYOS)/docker/compose,docker/compose:$(COMPOSE_VERSION))) $(if $(COMPOSE_FILE),$(call run,$(DOCKER_COMPOSE) $(patsubst %,-f %,$(COMPOSE_FILE)) -p $(if $(filter node,$(firstword $(subst /, ,$(STACK)))),$(NODE_COMPOSE_PROJECT_NAME),$(if $(filter User,$(firstword $(subst /, ,$(STACK)))),$(USER_COMPOSE_PROJECT_NAME),$(COMPOSE_PROJECT_NAME))) exec -T $(1) sh -c '$(2)')) endef -# function docker-build: Build docker image -define docker-build - $(call INFO,docker-build,$(1)$(comma) $(2)$(comma) $(3)) - $(eval path := $(patsubst %/,%,$(1))) - $(eval service := $(lastword $(subst /, ,$(path)))) - $(eval tag := $(or $(2),$(DOCKER_REPOSITORY)/$(service):$(DOCKER_IMAGE_TAG))) - $(eval target := $(subst ",,$(subst ',,$(or $(3),$(DOCKER_BUILD_TARGET))))) - $(eval image_id := $(shell docker images -q $(tag) 2>/dev/null)) - $(eval build_image := $(or $(filter false,$(DOCKER_BUILD_CACHE)),$(if $(image_id),,true))) - $(if $(build_image),$(RUN) docker build $(DOCKER_BUILD_ARGS) --build-arg DOCKER_BUILD_DIR="$(path)" $(DOCKER_BUILD_LABEL) --tag $(tag) $(if $(target),--target $(target)) -f $(path)/Dockerfile $(or $(DOCKER_BUILD_DIR),.),$(call INFO,docker image $(tag) has id $(image_id))) -endef -# function docker-commit: Commit docker image -define docker-commit - $(call INFO,docker-commit,$(1)$(comma) $(2)$(comma) $(3)$(comma) $(4)) - $(eval service := $(or $(1),$(DOCKER_SERVICE))) - $(eval container := $(or $(2),$(firstword $(shell $(call docker-compose,ps -q $(service) 2>/dev/null))))) - $(eval repository := $(or $(3),$(DOCKER_REPOSITORY)/$(service))) - $(eval tag := $(or $(4),$(DOCKER_IMAGE_TAG))) - $(RUN) docker commit $(container) $(repository):$(tag) -endef # function docker-push: Push docker image define docker-push $(call INFO,docker-push,$(1)$(comma) $(2)$(comma) $(3)) - $(eval service := $(or $(1),$(DOCKER_SERVICE))) - $(eval name := $(or $(2),$(DOCKER_REGISTRY_REPOSITORY)/$(service))) - $(eval tag := $(or $(3),$(DOCKER_IMAGE_TAG))) + $(eval service := $(or $(1),$(DOCKER_SERVICE))) + $(eval name := $(or $(2),$(DOCKER_REGISTRY_REPOSITORY)/$(service))) + $(eval tag := $(or $(3),$(DOCKER_IMAGE_TAG))) $(RUN) docker push $(name):$(tag) endef # function docker-stack: Call itself recursively for each stack to expand stacks @@ -104,8 +105,8 @@ endef # 2nd arg: versions, extract it from stack_names:stack_versions or 2nd arg define docker-stack $(call INFO,docker-stack,$(1)$(comma) $(2)) - $(eval stacks := $(firstword $(subst :, ,$(1)))) - $(eval versions := $(or $(if $(findstring :,$(1)),$(lastword $(subst :, ,$(1)))),$(2))) + $(eval stacks := $(firstword $(subst :, ,$(1)))) + $(eval versions := $(or $(if $(findstring :,$(1)),$(lastword $(subst :, ,$(1)))),$(2))) $(if $($(stacks)),$(foreach substack,$($(stacks)),$(call docker-stack,$(substack),$(if $(findstring :,$(1)),$(versions)))),$(call docker-stack-update,$(stacks),$(versions))) endef # function docker-stack-update: Update COMPOSE_FILE with .yml files of the stack @@ -120,21 +121,21 @@ endef # if $(path)/.env.dist file exists, update .env file define docker-stack-update $(call INFO,docker-stack-update,$(1)$(comma) $(2)$(comma) $(3)) - $(eval stack := $(patsubst %.yml,%,$(notdir $(1)))) - $(eval name := $(firstword $(subst :, ,$(stack)))) - $(eval version := $(or $(2),$(if $(findstring :,$(stack)),$(lastword $(subst :, ,$(stack))),latest))) - $(eval path := $(patsubst %/,%,$(or $(3),$(if $(findstring /,$(1)),$(if $(wildcard stack/$(1) stack/$(1).yml),stack/$(if $(findstring .yml,$(1)),$(dir $(1)),$(if $(wildcard stack/$(1).yml),$(dir $(1)),$(1))),$(dir $(1)))),stack/$(name)))) - $(eval COMPOSE_FILE += $(wildcard $(path)/$(name).yml $(path)/$(name).$(ENV).yml $(path)/$(name).$(ENV).$(version).yml $(path)/$(name).$(version).yml)) - $(eval COMPOSE_FILE := $(strip $(COMPOSE_FILE))) + $(eval stack := $(patsubst %.yml,%,$(notdir $(1)))) + $(eval name := $(firstword $(subst :, ,$(stack)))) + $(eval version := $(or $(2),$(if $(findstring :,$(stack)),$(lastword $(subst :, ,$(stack))),latest))) + $(eval path := $(patsubst %/,%,$(or $(3),$(if $(findstring /,$(1)),$(if $(wildcard stack/$(1) stack/$(1).yml),stack/$(if $(findstring .yml,$(1)),$(dir $(1)),$(if $(wildcard stack/$(1).yml),$(dir $(1)),$(1))),$(dir $(1)))),stack/$(name)))) + $(eval COMPOSE_FILE += $(wildcard $(path)/$(name).yml $(path)/$(name).$(ENV).yml $(path)/$(name).$(ENV).$(version).yml $(path)/$(name).$(version).yml)) + $(eval COMPOSE_FILE := $(strip $(COMPOSE_FILE))) $(if $(wildcard $(path)/.env.dist),$(call .env,,$(path)/.env.dist,$(wildcard $(CONFIG)/$(ENV)/$(APP)/.env $(path)/.env.$(ENV) .env))) endef # function docker-tag: Tag docker image define docker-tag $(call INFO,docker-tag,$(1)$(comma) $(2)$(comma) $(3)$(comma) $(4)$(comma) $(5)) - $(eval service := $(or $(1),$(DOCKER_SERVICE))) - $(eval source := $(or $(2),$(DOCKER_REPOSITORY)/$(service))) - $(eval source_tag := $(or $(3),$(DOCKER_IMAGE_TAG))) - $(eval target := $(or $(4),$(DOCKER_REGISTRY_REPOSITORY)/$(service))) - $(eval target_tag := $(or $(5),$(source_tag))) + $(eval service := $(or $(1),$(DOCKER_SERVICE))) + $(eval source := $(or $(2),$(DOCKER_REPOSITORY)/$(service))) + $(eval source_tag := $(or $(3),$(DOCKER_IMAGE_TAG))) + $(eval target := $(or $(4),$(DOCKER_REGISTRY_REPOSITORY)/$(service))) + $(eval target_tag := $(or $(5),$(source_tag))) $(RUN) docker tag $(source):$(source_tag) $(target):$(target_tag) endef diff --git a/make/apps/def.mk b/make/apps/def.mk index 98942b7..c2720ef 100644 --- a/make/apps/def.mk +++ b/make/apps/def.mk @@ -1,6 +1,6 @@ APP_DIR ?= $(CURDIR) APP_DOMAIN ?= $(addsuffix .,$(filter-out master,$(ENV)))$(USER).$(DOMAIN) -APP_HOST ?= $(addsuffix .,$(APP))$(APP_DOMAIN) +APP_HOST ?= $(addsuffix .,$(APP_NAME))$(APP_DOMAIN) APP_INSTALLED ?= $(APPS) APP_PARENT ?= $(MONOREPO) APP_PARENT_DIR ?= $(MONOREPO_DIR) @@ -23,7 +23,4 @@ ENV_VARS += APP_DIR APP_DOMAIN APP_HOST APP_PATH APP_URL MOUNT_NFS ?= false NFS_CONFIG ?= addr=$(NFS_HOST),actimeo=3,intr,noacl,noatime,nocto,nodiratime,nolock,soft,rsize=32768,wsize=32768,tcp,rw,vers=3 NFS_HOST ?= host.docker.internal -PROJECT_NAME ?= $(COMPOSE_PROJECT_NAME) -SERVICE_NAME ?= $(COMPOSE_SERVICE_NAME) -SERVICE_VERSION ?= $(BUILD_DATE)-$(VERSION) SERVICES ?= $(DOCKER_SERVICES) diff --git a/make/apps/docker.mk b/make/apps/docker.mk index 4b29e68..6a21878 100644 --- a/make/apps/docker.mk +++ b/make/apps/docker.mk @@ -11,8 +11,8 @@ docker-build: docker-images-myos docker-build-%: if grep -q DOCKER_REPOSITORY docker/$*/Dockerfile 2>/dev/null; then $(eval DOCKER_BUILD_ARGS:=$(subst $(DOCKER_REPOSITORY),$(USER_DOCKER_REPOSITORY),$(DOCKER_BUILD_ARGS))) true; fi $(if $(wildcard docker/$*/Dockerfile),$(call docker-build,docker/$*)) - $(if $(findstring :,$*),$(eval DOCKERFILES := $(wildcard docker/$(subst :,/,$*)/Dockerfile)),$(eval DOCKERFILES := $(wildcard docker/$*/*/Dockerfile))) - $(foreach dockerfile,$(DOCKERFILES),$(call docker-build,$(dir $(dockerfile)),$(DOCKER_REPOSITORY)/$(word 2,$(subst /, ,$(dir $(dockerfile)))):$(lastword $(subst /, ,$(dir $(dockerfile)))),"") && true) + $(if $(findstring :,$*),$(eval DOCKER_FILE := $(wildcard docker/$(subst :,/,$*)/Dockerfile)),$(eval DOCKER_FILE := $(wildcard docker/$*/*/Dockerfile))) + $(foreach dockerfile,$(DOCKER_FILE),$(call docker-build,$(dir $(dockerfile)),$(DOCKER_REPOSITORY)/$(word 2,$(subst /, ,$(dir $(dockerfile)))):$(lastword $(subst /, ,$(dir $(dockerfile)))),"") && true) # target docker-commit: Call docker-commit for each SERVICES .PHONY: docker-commit diff --git a/make/common.mk b/make/common.mk index 85649ae..ff38144 100644 --- a/make/common.mk +++ b/make/common.mk @@ -1,5 +1,3 @@ -CMDS += apps-install install-app - ## # COMMON @@ -16,31 +14,26 @@ $(APP): myos-user app-%: $(eval app := $(subst -$(lastword $(subst -, ,$*)),,$*)) $(eval command := $(lastword $(subst -, ,$*))) - $(if $(findstring -,$*), \ - $(if $(filter app-$(command),$(.VARIABLES)), \ - $(eval APP := $(app)) \ - $(eval APP_DIR := $(RELATIVE)$(app)) \ - $(eval COMPOSE_PROJECT_NAME := $(USER)-$(app)-$(ENV)$(addprefix -,$(subst /,,$(subst -,,$(APP_PATH))))) \ - $(eval DOCKER_REPOSITORY := $(subst -,/,$(subst _,/,$(COMPOSE_PROJECT_NAME)))) \ - $(eval DOCKER_IMAGE_TAG := $(if $(filter $(ENV),$(ENV_DEPLOY)),$(VERSION),$(if $(DRONE_BUILD_NUMBER),$(DRONE_BUILD_NUMBER),latest))) \ - $(eval DOCKER_IMAGE := $(DOCKER_REPOSITORY)/$(app):$(DOCKER_IMAGE_TAG)) \ + $(if $(filter app-$(command),$(.VARIABLES)), \ + $(call app-bootstrap,$(app)) \ $(call app-$(command)) \ - ) \ + , \ + $(call app-bootstrap,$*) \ ) # target app-required-install: Call app-install for each APP_REQUIRED .PHONY: app-required-install -app-required-install: myos-user +app-required-install: $(foreach url,$(APP_REQUIRED),$(call app-install,$(url))) # target apps-build: Call app-build for each APPS .PHONY: apps-build -apps-build: myos-user +apps-build: $(foreach app,$(APPS),$(call app-build,$(RELATIVE)$(app))) # target apps-install install-app: Call app-install for each ARGS .PHONY: apps-install install-app -apps-install install-app: myos-user app-required-install +apps-install install-app: app-required-install $(foreach url,$(ARGS),$(call app-install,$(url))) # target apps-update: Call app-update target for each APPS @@ -76,7 +69,7 @@ update-app-%: % ; # target update-config: Update config files .PHONY: update-config -update-config: myos-user +update-config: $(call app-update,$(CONFIG_REPOSITORY),$(CONFIG)) # target update-hosts: Update /etc/hosts diff --git a/make/def.app.mk b/make/def.app.mk index dc84081..2efdfe1 100644 --- a/make/def.app.mk +++ b/make/def.app.mk @@ -1,60 +1,138 @@ -# function app-build: Call docker-build or docker-compose-build in app 1 +# function app-bootstrap: Define custom variables for app 1 in dir 2 with name 3 and type 4 +define app-bootstrap + $(call INFO,app-bootstrap,$(1)$(comma) $(2$(comma) $(3))$(comma) $(4)) + $(eval APP := $(or $(1), $(APP))) + $(eval APP_DIR := $(or $(2), $(RELATIVE)$(APP))) + $(eval APP_NAME := $(or $(3),$(subst -,,$(subst .,,$(call LOWERCASE,$(APP)))))) + $(eval APP_TYPE := $(or $(4), git)) + $(eval DOCKER_BUILD_DIR := $(APP_DIR)) + $(eval DOCKER_FILE := $(wildcard $(APP_DIR)/docker/*/Dockerfile $(APP_DIR)/*/Dockerfile $(APP_DIR)/Dockerfile)) + $(eval COMPOSE_FILE := $(wildcard $(APP_DIR)/docker-compose.yml $(APP_DIR)/docker-compose.$(ENV).yml $(APP_DIR)/docker/docker-compose.yml $(foreach file,$(patsubst $(APP_DIR)/docker/docker-compose.%,%,$(basename $(wildcard $(APP_DIR)/docker/docker-compose.*.yml))),$(if $(filter true,$(COMPOSE_FILE_$(file)) $(COMPOSE_FILE_$(call UPPERCASE,$(file)))),$(APP_DIR)/docker/docker-compose.$(file).yml)))) + $(if $(wildcard $(APP_DIR)/.env.sample), + $(call .env,$(APP_DIR)/.env,$(APP_DIR)/.env.sample) + , + $(call .env,$(APP_DIR)/.env) + ) + +endef + +# function app-build: Call docker-build for each Dockerfile in dir 1 define app-build - $(call INFO,app-build,$(1)$(comma) $(2)) - $(eval dir := $(or $(1), $(APP_DIR))) - $(eval DOCKER_BUILD_DIR := $(dir)) - $(if $(wildcard $(dir)/Dockerfile), \ - $(call docker-build,$(dir),,''), \ - $(call ERROR,Unable to find docker file $(dir)/Dockerfile) \ + $(call INFO,app-build,$(1)) + $(if $(filter-out $(APP_DIR),$(1)), + $(eval DOCKER_FILE := $(wildcard $(1)/docker/*/Dockerfile $(1)/*/Dockerfile $(1)/Dockerfile)) + ) + $(if $(DOCKER_FILE), \ + $(foreach dockerfile,$(DOCKER_FILE), + $(call app-docker,$(dockerfile)) + $(call docker-build, $(dir $(dockerfile)), $(DOCKER_IMAGE), "" ) + ), + $(call ERROR,Unable to find any Dockerfile in dir: $(or $(1),$(APP_DIR))) ) endef -# function app-install: Run 'git clone url 1 dir 2' or Call app-update with url 1 dir 2 +# function app-docker: Define custom variables for Dockerfile 1 +define app-docker + $(call INFO,app-docker,$(1)) + $(eval dir := $(or $(APP_DIR))) + $(eval dockerfile := $(or $(1))) + $(if $(wildcard $(dockerfile)), + $(eval service := $(or $(SERVICE),$(subst .,,$(call LOWERCASE,$(lastword $(subst /, ,$(patsubst %/Dockerfile,%,$(dockerfile)))))),undefined)) + $(eval docker := ${COMPOSE_SERVICE_NAME}-$(service)) + $(eval DOCKER_IMAGE := $(DOCKER_REPOSITORY)/$(service):$(DOCKER_IMAGE_TAG)) + $(eval DOCKER_LABELS := SERVICE_NAME=$(docker) SERVICE_TAGS=urlprefix-$(service).$(APP_DOMAIN)/$(APP_PATH)) + $(eval DOCKER_NAME := $(docker)) + $(eval DOCKER_RUN_NAME := --name $(DOCKER_NAME)) + , + $(call ERROR,Unable to find Dockerfile: $(dockerfile)) + ) +endef + +# function app-down: Call docker rm for each Dockerfile in dir 1 +define app-down + $(call INFO,app-down,$(1)) + $(if $(filter-out $(APP_DIR),$(1)), + $(eval DOCKER_FILE := $(wildcard $(1)/docker/*/Dockerfile $(1)/*/Dockerfile $(1)/Dockerfile)) + ) + $(if $(DOCKER_FILE), \ + $(foreach dockerfile,$(DOCKER_FILE), + $(call app-docker,$(dockerfile)) + $(if $(shell docker ps -q -f name=$(DOCKER_NAME) 2>/dev/null), + $(shell docker rm -f $(DOCKER_NAME)) + , + $(call ERROR,Unable to find docker $(DOCKER_NAME)) + ) + ), + $(call ERROR,Unable to find any Dockerfile in dir: $(or $(1),$(APP_DIR))) + ) +endef + +# function app-install: Run 'git clone url 1 dir 2' define app-install $(call INFO,app-install,$(1)$(comma) $(2)) - $(eval url := $(or $(1), $(APP_REPOSITORY_URL))) - $(eval dir := $(or $(2), $(RELATIVE)$(lastword $(subst /, ,$(url))))) - $(if $(wildcard $(dir)/.git), \ - $(call app-update,$(url),$(dir)), \ - $(RUN) git clone $(QUIET) $(url) $(dir) \ + $(eval url := $(or $(1), $(APP_REPOSITORY_URL))) + $(eval dir := $(or $(2), $(RELATIVE)$(lastword $(subst /, ,$(url))))) + $(if $(wildcard $(dir)/.git), + $(call INFO,app: $(url) already installed in dir: $(dir)), + $(RUN) git clone $(QUIET) $(url) $(dir) ) endef # function app-rebuild: Call app-build with DOCKER_BUILD_CACHE=false define app-rebuild - $(call INFO,app-rebuild,$(1)$(comma) $(2)) + $(call INFO,app-rebuild,$(1)) $(eval DOCKER_BUILD_CACHE := false) - $(call app-build,$(1),$(2)) + $(call app-build,$(1)) endef -# function app-run: Call docker-run or docker-compose-run in app 1 +# function app-run: Call docker-run for each Dockerfile in dir 1 with args 2 define app-run $(call INFO,app-run,$(1)$(comma) $(2)) - $(eval image := $(or $(1), $(DOCKER_IMAGE))) - $(eval args := $(or $(2), $(ARGS))) - $(if $(shell docker images -q $(image) 2>/dev/null), \ - $(call docker-run,$(args),$(image)), \ - $(call ERROR,Unable to find docker image $(image)) \ + $(if $(filter-out $(APP_DIR),$(1)), + $(eval DOCKER_FILE := $(wildcard $(1)/docker/*/Dockerfile $(1)/*/Dockerfile $(1)/Dockerfile)) + ) + $(eval args := $(or $(2), $(ARGS))) + $(eval DOCKER_RUN_OPTIONS += -it) + $(if $(DOCKER_FILE), \ + $(foreach dockerfile,$(DOCKER_FILE), + $(call app-docker,$(dockerfile)) + $(if $(shell docker images -q $(DOCKER_IMAGE) 2>/dev/null), + $(call docker-run,$(args)) + , + $(call ERROR,Unable to find docker image $(DOCKER_IMAGE)) + ) + ), + $(call ERROR,Unable to find any Dockerfile in dir: $(or $(1),$(APP_DIR))) ) endef -# function app-up: Call docker-run in app 1 +# function app-up: Call docker-run (-d) for each Dockerfile in dir 1 define app-up $(call INFO,app-up,$(1)) - $(eval image := $(or $(1), $(DOCKER_IMAGE))) - $(if $(shell docker images -q $(image) 2>/dev/null), \ - $(call docker-run,$(image)), \ - $(call ERROR,Unable to find docker image $(image)) \ + $(if $(filter-out $(APP_DIR),$(1)), + $(eval DOCKER_FILE := $(wildcard $(1)/docker/*/Dockerfile $(1)/*/Dockerfile $(1)/Dockerfile)) + ) + $(eval DOCKER_RUN_OPTIONS += -d) + $(if $(DOCKER_FILE), \ + $(foreach dockerfile,$(DOCKER_FILE), + $(call app-docker,$(dockerfile)) + $(if $(shell docker images -q $(DOCKER_IMAGE) 2>/dev/null), + $(call docker-run,$(args)) + , + $(call ERROR,Unable to find docker image $(DOCKER_IMAGE)) + ) + ), + $(call ERROR,Unable to find any Dockerfile in dir: $(or $(1),$(APP_DIR))) ) endef # function app-update: Run 'cd dir 1 && git pull' or Call app-install define app-update $(call INFO,app-update,$(1)$(comma) $(2)) - $(eval url := $(or $(1), $(APP_REPOSITORY_URL))) - $(eval dir := $(or $(2), $(APP_DIR))) - $(if $(wildcard $(dir)/.git), \ - $(RUN) sh -c 'cd $(dir) && git pull $(QUIET)', \ - $(call app-install,$(url),$(dir)) \ + $(eval url := $(or $(1), $(APP_REPOSITORY_URL))) + $(eval dir := $(or $(2), $(APP_DIR))) + $(if $(wildcard $(dir)/.git), + $(RUN) sh -c 'cd $(dir) && git pull $(QUIET)', + $(call app-install,$(url),$(dir)) ) endef diff --git a/make/def.docker.mk b/make/def.docker.mk index 293b135..7a83aa2 100644 --- a/make/def.docker.mk +++ b/make/def.docker.mk @@ -8,8 +8,9 @@ DOCKER_NETWORK_PRIVATE ?= $(USER_COMPOSE_PROJECT_NAME) DOCKER_NETWORK_PUBLIC ?= $(NODE_COMPOSE_PROJECT_NAME) # DOCKER_RUN: if empty, run system command, else run it in a docker DOCKER_RUN ?= $(if $(filter-out false False FALSE,$(DOCKER)),$(DOCKER)) +DOCKER_RUN_LABELS ?= $(patsubst %,-l %,$(DOCKER_LABELS)) # DOCKER_RUN_OPTIONS: default options of `docker run` command -DOCKER_RUN_OPTIONS += --rm +DOCKER_RUN_OPTIONS += --rm --network $(DOCKER_NETWORK) # DOCKER_RUN_VOLUME: options -v of `docker run` command to mount additionnal volumes DOCKER_RUN_VOLUME += -v /var/run/docker.sock:/var/run/docker.sock DOCKER_RUN_WORKDIR ?= -w $(PWD) @@ -39,7 +40,6 @@ DOCKER_INTERNAL_DOCKER_HOST ?= $(shell /sbin/ip addr show docker0 2>/dev/nul endif ifeq ($(DRONE), true) -DOCKER_RUN_OPTIONS := --rm --network $(DOCKER_NETWORK) # When running docker command in drone, we are already in a docker (dind). # Whe need to find the volume mounted in the current docker (runned by drone) to mount it in our docker command. # If we do not mount the volume in our docker, we wont be able to access the files in this volume as the /drone/src directory would be empty. @@ -74,7 +74,7 @@ endif ## attention: arg 2 should end with slash or space define run $(call INFO,run,$(1)$(comma) $(2)) - $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(DOCKER_SSH_AUTH) $(2)$(1) + $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_LABELS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(DOCKER_SSH_AUTH) $(DOCKER_RUN_NAME) $(2)$(1) endef else @@ -83,7 +83,7 @@ SHELL := /bin/bash # function docker-run DOCKER=false: Run docker image 2 with arg 1 define docker-run $(call INFO,docker-run,$(1)$(comma) $(2)) - $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(or $(2),$(DOCKER_IMAGE)) $(1) + $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_LABELS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(DOCKER_RUN_NAME) $(or $(2),$(DOCKER_IMAGE)) $(1) endef # function exec DOCKER=false: Call env-exec with arg 1 or SHELL define exec diff --git a/make/def.mk b/make/def.mk index 2e30a1b..ed78619 100644 --- a/make/def.mk +++ b/make/def.mk @@ -7,7 +7,7 @@ quote ?= ' lbracket ?= ( rbracket ?= ) APP ?= $(if $(wildcard .git),$(notdir $(CURDIR))) -APP_NAME ?= $(APP) +APP_NAME ?= $(subst _,,$(subst -,,$(subst .,,$(call LOWERCASE,$(APP))))) APP_TYPE ?= $(if $(SUBREPO),subrepo) $(if $(filter .,$(MYOS)),myos) APPS ?= $(if $(MONOREPO),$(sort $(patsubst $(MONOREPO_DIR)/%/.git,%,$(wildcard $(MONOREPO_DIR)/*/.git)))) APPS_NAME ?= $(foreach app,$(APPS),$(or $(shell awk -F '=' '$$1 == "APP" {print $$2}' $(or $(wildcard $(MONOREPO_DIR)/$(app)/.env),$(wildcard $(MONOREPO_DIR)/$(app)/.env.$(ENV)),$(MONOREPO_DIR)/$(app)/.env.dist) 2>/dev/null),$(app))) @@ -16,7 +16,7 @@ CMD_APK_INSTALL ?= $(if $(shell type -p apk),apk --no-cache --up CMD_APK_REMOVE ?= $(if $(shell type -p apk),apk --no-cache del) CMD_APT_INSTALL ?= $(if $(shell type -p apt-get),apt-get update && apt-get -fy install) CMD_APT_REMOVE ?= $(if $(shell type -p apt-get),apt-get -fy remove) -CMDS ?= app-%-run exec exec:% exec@% run run:% run@% +CMDS ?= app-%-run apps-install exec exec:% exec@% install-app run run:% run@% COLOR_BLUE ?= \033[01;34m COLOR_BROWN ?= \033[33m COLOR_CYAN ?= \033[36m diff --git a/stack/cloud/.env.dist b/stack/cloud/.env.dist new file mode 100644 index 0000000..ad1e320 --- /dev/null +++ b/stack/cloud/.env.dist @@ -0,0 +1,5 @@ +NEXTCLOUD_MYSQL_DATABASE=${USER}-nextcloud-${ENV} +NEXTCLOUD_MYSQL_HOST=mysql +NEXTCLOUD_MYSQL_PASSWORD=nextcloud +NEXTCLOUD_MYSQL_USER=${USER}-nextcloud-${ENV} +NEXTCLOUD_SERVICE_80_TAGS=urlprefix-nextcloud.${APP_DOMAIN}/ diff --git a/stack/cloud/nextcloud.yml b/stack/cloud/nextcloud.yml new file mode 100644 index 0000000..f4d790e --- /dev/null +++ b/stack/cloud/nextcloud.yml @@ -0,0 +1,33 @@ +version: '3.6' + +services: + nextcloud: + image: nextcloud:production-apache + environment: + - MYSQL_DATABASE=${NEXTCLOUD_MYSQL_DATABASE} + - MYSQL_HOST=${NEXTCLOUD_MYSQL_HOST} + - MYSQL_PASSWORD=${NEXTCLOUD_MYSQL_PASSWORD} + - MYSQL_USER=${NEXTCLOUD_MYSQL_USER} + labels: + - SERVICE_80_CHECK_TCP=true + - SERVICE_80_NAME=${COMPOSE_SERVICE_NAME}-nextcloud-80 + - SERVICE_80_TAGS=${NEXTCLOUD_SERVICE_80_TAGS} + networks: + - private + - public + ports: + - 80 + volumes: + - nextcloud:/var/www/html + restart: always + +volumes: + nextcloud: + +networks: + private: + external: true + name: ${DOCKER_NETWORK_PRIVATE} + public: + external: true + name: ${DOCKER_NETWORK_PUBLIC} diff --git a/stack/node/backup/.env.dist b/stack/node/backup/.env.dist new file mode 100644 index 0000000..5575c8e --- /dev/null +++ b/stack/node/backup/.env.dist @@ -0,0 +1,2 @@ +NODE_RESTIC_REPOSITORY= +NODE_RESTIC_PASSWORD= diff --git a/stack/node/backup/restic.yml b/stack/node/backup/restic.yml new file mode 100644 index 0000000..6243944 --- /dev/null +++ b/stack/node/backup/restic.yml @@ -0,0 +1,27 @@ +version: "3.6" + +services: + restic: + image: mazzolino/restic:1.1.1 + hostname: ${HOSTNAME} + environment: + BACKUP_CRON: "30 3 * * *" + RESTIC_REPOSITORY: ${NODE_RESTIC_REPOSITORY} + RESTIC_PASSWORD: ${NODE_RESTIC_PASSWORD} + RESTIC_BACKUP_SOURCES: /var/lib/docker/volumes + RESTIC_BACKUP_TAGS: docker-volumes + RESTIC_FORGET_ARGS: --prune --keep-last 14 --keep-daily 1 + TZ: Europe/Paris + networks: + - private + volumes: + - restic:/root/.config + - /var/lib/docker/volumes:/var/lib/docker/volumes:ro + +volumes: + restic: + +networks: + private: + external: true + name: ${DOCKER_NETWORK_PRIVATE} diff --git a/stack/node/mail/mail.yml b/stack/node/mail/mailserver.yml similarity index 97% rename from stack/node/mail/mail.yml rename to stack/node/mail/mailserver.yml index 9047a84..d5f10e8 100644 --- a/stack/node/mail/mail.yml +++ b/stack/node/mail/mailserver.yml @@ -130,6 +130,9 @@ services: - SERVICE_995_IGNORE=true - SERVICE_4190_CHECK_TCP=true - SERVICE_4190_NAME=${NODE_COMPOSE_SERVICE_NAME}-mailserver-4190 + networks: + - private + - public ports: - "25:25" - "143:143" @@ -153,3 +156,11 @@ volumes: myos: external: true name: ${NODE_DOCKER_VOLUME} + +networks: + private: + external: true + name: ${DOCKER_NETWORK_PRIVATE} + public: + external: true + name: ${DOCKER_NETWORK_PUBLIC}