Skip to content

Instantly share code, notes, and snippets.

@mpneuried
Last active February 21, 2024 09:23
Show Gist options
  • Save mpneuried/0594963ad38e68917ef189b4e6a269db to your computer and use it in GitHub Desktop.
Save mpneuried/0594963ad38e68917ef189b4e6a269db to your computer and use it in GitHub Desktop.
Simple Makefile to build, run, tag and publish a docker containier to AWS-ECR
# Port to run the container
PORT=4000
# Until here you can define all the individual configurations for your app
# You have to define the values in {}
APP_NAME=my-super-app
DOCKER_REPO={account-nr}.dkr.ecr.{region}.amazonaws.com
# optional aws-cli options
AWS_CLI_PROFILE={aws-cli-profile}
AWS_CLI_REGION={aws-cli-region}
# import config.
# You can change the default config with `make cnf="config_special.env" build`
cnf ?= config.env
include $(cnf)
export $(shell sed 's/=.*//' $(cnf))
# import deploy config
# You can change the default deploy config with `make cnf="deploy_special.env" release`
dpl ?= deploy.env
include $(dpl)
export $(shell sed 's/=.*//' $(dpl))
# grep the version from the mix file
VERSION=$(shell ./version.sh)
# HELP
# This will output the help for each task
# thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
.PHONY: help
help: ## This help.
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.DEFAULT_GOAL := help
# DOCKER TASKS
# Build the container
build: ## Build the container
docker build -t $(APP_NAME) .
build-nc: ## Build the container without caching
docker build --no-cache -t $(APP_NAME) .
run: ## Run container on port configured in `config.env`
docker run -i -t --rm --env-file=./config.env -p=$(PORT):$(PORT) --name="$(APP_NAME)" $(APP_NAME)
up: build run ## Run container on port configured in `config.env` (Alias to run)
stop: ## Stop and remove a running container
docker stop $(APP_NAME); docker rm $(APP_NAME)
release: build-nc publish ## Make a release by building and publishing the `{version}` ans `latest` tagged containers to ECR
# Docker publish
publish: repo-login publish-latest publish-version ## Publish the `{version}` ans `latest` tagged containers to ECR
publish-latest: tag-latest ## Publish the `latest` taged container to ECR
@echo 'publish latest to $(DOCKER_REPO)'
docker push $(DOCKER_REPO)/$(APP_NAME):latest
publish-version: tag-version ## Publish the `{version}` taged container to ECR
@echo 'publish $(VERSION) to $(DOCKER_REPO)'
docker push $(DOCKER_REPO)/$(APP_NAME):$(VERSION)
# Docker tagging
tag: tag-latest tag-version ## Generate container tags for the `{version}` ans `latest` tags
tag-latest: ## Generate container `{version}` tag
@echo 'create tag latest'
docker tag $(APP_NAME) $(DOCKER_REPO)/$(APP_NAME):latest
tag-version: ## Generate container `latest` tag
@echo 'create tag $(VERSION)'
docker tag $(APP_NAME) $(DOCKER_REPO)/$(APP_NAME):$(VERSION)
# HELPERS
# generate script to login to aws docker repo
CMD_REPOLOGIN := "eval $$\( aws ecr"
ifdef AWS_CLI_PROFILE
CMD_REPOLOGIN += " --profile $(AWS_CLI_PROFILE)"
endif
ifdef AWS_CLI_REGION
CMD_REPOLOGIN += " --region $(AWS_CLI_REGION)"
endif
CMD_REPOLOGIN += " get-login --no-include-email \)"
# login to AWS-ECR
repo-login: ## Auto login to AWS-ECR unsing aws-cli
@eval $(CMD_REPOLOGIN)
version: ## Output the current version
@echo $(VERSION)
### THIS IST THE VERSION WITH docker-compose
# import config.
# You can change the default config with `make cnf="config_special.env" build`
cnf ?= config.env
include $(cnf)
export $(shell sed 's/=.*//' $(cnf))
# import deploy config
# You can change the default deploy config with `make cnf="deploy_special.env" release`
dpl ?= deploy.env
include $(dpl)
export $(shell sed 's/=.*//' $(dpl))
# grep the version from the mix file
VERSION=$(shell ./version.sh)
# HELP
# This will output the help for each task
# thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
.PHONY: help
help: ## This help.
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.DEFAULT_GOAL := help
# DOCKER TASKS
# Build the container
build: ## Build the release and develoment container. The development
docker-compose build --no-cache $(APP_NAME)
docker-compose run $(APP_NAME) grunt build
docker build -t $(APP_NAME) .
run: stop ## Run container on port configured in `config.env`
docker run -i -t --rm --env-file=./config.env -p=$(PORT):$(PORT) --name="$(APP_NAME)" $(APP_NAME)
dev: ## Run container in development mode
docker-compose build --no-cache $(APP_NAME) && docker-compose run $(APP_NAME)
# Build and run the container
up: ## Spin up the project
docker-compose up --build $(APP_NAME)
stop: ## Stop running containers
docker stop $(APP_NAME)
rm: stop ## Stop and remove running containers
docker rm $(APP_NAME)
clean: ## Clean the generated/compiles files
echo "nothing clean ..."
# Docker release - build, tag and push the container
release: build publish ## Make a release by building and publishing the `{version}` ans `latest` tagged containers to ECR
# Docker publish
publish: repo-login publish-latest publish-version ## publish the `{version}` ans `latest` tagged containers to ECR
publish-latest: tag-latest ## publish the `latest` taged container to ECR
@echo 'publish latest to $(DOCKER_REPO)'
docker push $(DOCKER_REPO)/$(APP_NAME):latest
publish-version: tag-version ## publish the `{version}` taged container to ECR
@echo 'publish $(VERSION) to $(DOCKER_REPO)'
docker push $(DOCKER_REPO)/$(APP_NAME):$(VERSION)
# Docker tagging
tag: tag-latest tag-version ## Generate container tags for the `{version}` ans `latest` tags
tag-latest: ## Generate container `{version}` tag
@echo 'create tag latest'
docker tag $(APP_NAME) $(DOCKER_REPO)/$(APP_NAME):latest
tag-version: ## Generate container `latest` tag
@echo 'create tag $(VERSION)'
docker tag $(APP_NAME) $(DOCKER_REPO)/$(APP_NAME):$(VERSION)
# HELPERS
# generate script to login to aws docker repo
CMD_REPOLOGIN := "aws ecr"
ifdef AWS_CLI_PROFILE
CMD_REPOLOGIN += "--profile $(AWS_CLI_PROFILE)"
endif
ifdef AWS_CLI_REGION
CMD_REPOLOGIN += "--region $(AWS_CLI_REGION)"
endif
CMD_REPOLOGIN += "get-login --no-include-email"
repo-login: ## Auto login to AWS-ECR unsing aws-cli
@eval $(CMD_REPOLOGIN)
version: ## output to version
@echo $(VERSION)
# INSTALL
# - copy the files deploy.env, config.env, version.sh and Makefile to your repo
# - replace the vars in deploy.env
# - define the version script
# Build the container
make build
# Build and publish the container
make release
# Publish a container to AWS-ECR.
# This includes the login to the repo
make publish
# Run the container
make run
# Build an run the container
make up
# Stop the running container
make stop
# Build the container with differnt config and deploy file
make cnf=another_config.env dpl=another_deploy.env build
# Example version script.
# Please choose one version or create your own
# Node.js: grep the version from a package.json file with jq
jq -rM '.version' package.json
# Elixir: grep the version from a mix file
cat mix.exs | grep version | grep '\([0-9]\+\.\?\)\{3\}' -o
@SpyPower
Copy link

SpyPower commented Jul 8, 2019

Escaping colon like this worked: $(PORT):$(PORT)

You mentioned on https://gist.github.com/mpneuried/0594963ad38e68917ef189b4e6a269db#gistcomment-2896932 that you used -p $(PORT):$(PORT) and it caused make to treat that line as a circular dependency and then you mentioned on the quoted text exactly the same as a solution. Can you please clarify?

@SamyCoenen
Copy link

Isn't it a best practice to specify all as your default target instead of help https://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets

@cbrunnkvist
Copy link

@SpyPower that error must have been due to @fd98279 forgetting to tab-indent the line properly. Unless indented, make would think the whole line is a target: dependencies kind of line and get confused by the colon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment