--- version: '3' tasks: fat: cmds: - task: :docker:update:version - task: fat:build fat:build: deps: - :install:software:docker - :install:software:jq desc: Build a normal Docker container from the Dockerfile summary: | # Build Docker Container from Dockerfile This task builds a normal Docker container. It expects the Dockerfile to be named `Dockerfile` and for it to be in the root of the repository. For more information on building Docker containers, see [Docker's build guide](https://docs.docker.com/engine/reference/commandline/build/). vars: BUILD_DATE: sh: type git &> /dev/null && git show -s --format=%cI REVISION: sh: type git &> /dev/null && git rev-parse HEAD SLUG: sh: jq -r '.blueprint.slug' package.json TAG_POST: '{{if .CLI_ARGS}}{{if ne .DOCKER_BASE_TAG .CLI_ARGS}}-{{.CLI_ARGS}}{{end}}{{end}}' VERSION: sh: jq -r '.version' package.json run: when_changed hide: sh: '[ ! -f Dockerfile ]' log: error: Error building `{{.DOCKER_IMAGE}}:{{.VERSION}}` start: Building Docker container `{{.DOCKER_IMAGE}}:{{.VERSION}}` (also tagged as latest) success: Successfully built Docker container named `{{.DOCKER_IMAGE}}:{{.VERSION}}` cmds: - .config/log info 'Running `docker build --build-arg BUILD_DATE={{.BUILD_DATE}} --build-arg REVISION={{.REVISION}} --build-arg VERSION={{.VERSION}} --tag {{.DOCKER_IMAGE}}:latest{{.TAG_POST}} {{if (contains "codeclimate" .CLI_ARGS)}} --tag codeclimate/codeclimate-{{.SLUG}}{{end}}{{if .CLI_ARGS}} --target {{.CLI_ARGS}}{{end}} .`' - docker build --build-arg BUILD_DATE={{.BUILD_DATE}} --build-arg REVISION={{.REVISION}} --build-arg VERSION={{.VERSION}} --tag {{.DOCKER_IMAGE}}:latest{{.TAG_POST}} {{if (contains "codeclimate" .CLI_ARGS)}} --tag codeclimate/codeclimate-{{.SLUG}}{{end}} {{if .CLI_ARGS}} --target {{.CLI_ARGS}}{{end}} . slim: deps: - :install:software:docker - :install:software:docker-slim desc: Build a slim version of the Docker image hide: sh: '[ ! -f Dockerfile ]' summary: | # Build a compressed and secure container from the `regular` Docker image This task takes the Docker container generated by running `task build:normal` and compresses it using DockerSlim. Compressing it actually makes the container more secure too because there is a smaller attack surface with unnecessary tools and services removed. For more information, see [DockerSlim's GitHub page](https://github.com/docker-slim/docker-slim). cmds: - task: fat - task: slim:command - task: slim:finish slim:command: vars: DIND_MOUNT: sh: | if [ "$(jq -r '.blueprint.dockerInDocker' package.json)" == 'true' ]; then echo "--mount {{.DIND_MOUNT_MAPPING}} " fi SLIM_COMMAND: sh: | COMMAND_TYPE="$(jq -r '.blueprint.dockerSlimCommand | type' package.json)" if [ "$COMMAND_TYPE" == 'string' ]; then echo "$(jq -r '.blueprint.dockerSlimCommand' package.json)" else COMMAND="$(jq --arg type "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}$(jq -r '.blueprint.slug' package.json){{end}}" \ -r '.blueprint.dockerSlimCommand[$type]' package.json)" if [ "$COMMAND" != 'null' ]; then echo "$(jq --arg type "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}$(jq -r '.blueprint.slug' package.json){{end}}" \ -r '.blueprint.dockerSlimCommand[$type]' package.json)" fi fi TAG_POST: '{{if .CLI_ARGS}}{{if ne .DOCKER_BASE_TAG .CLI_ARGS}}-{{.CLI_ARGS}}{{end}}{{end}}' log: error: Error building `{{.DOCKER_IMAGE}}:slim` with `docker-slim` start: Building Docker container named `{{.DOCKER_IMAGE}}:slim` success: Successfully built Docker container named `{{.DOCKER_IMAGE}}:slim` cmds: - > .config/log info 'Running `docker-slim build {{.DIND_MOUNT}}--tag {{.DOCKER_IMAGE}}:slim{{.TAG_POST}} {{if (contains "codeclimate" .CLI_ARGS)}}--tag codeclimate/codeclimate-{{.SLUG}}:slim {{end}} {{.SLIM_COMMAND | replace "'" "\""}} {{.DOCKER_IMAGE}}:latest{{.TAG_POST}}`' - > docker-slim build {{.DIND_MOUNT}}--tag {{.DOCKER_IMAGE}}:slim{{.TAG_POST}} {{if (contains "codeclimate" .CLI_ARGS)}}--tag codeclimate/codeclimate-{{.SLUG}}:slim {{end}} {{.SLIM_COMMAND | replace "'" "\""}} {{.DOCKER_IMAGE}}:latest{{.TAG_POST}} slim:finish: deps: - slim:prettier - slim:sizes slim:prettier: deps: - :install:npm:prettier vars: IMAGE_SLUG: sh: jq -r '.blueprint.slug' package.json log: error: Failed to format `slim.report.json` with Prettier start: Formatting `slim.report.json` with Prettier success: Formatted `slim.report.json` with Prettier cmds: - prettier --write slim.report.json > /dev/null - mv slim.report.json docs/slim{{if .CLI_ARGS}}.{{.CLI_ARGS}}{{end}}.report.json slim:sizes: cmds: - task: slim:sizes:assets - task: slim:sizes:calculate - task: slim:sizes:clean slim:sizes:assets: deps: - :install:software:docker - :install:software:gzip vars: SLUG: sh: echo "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}$(jq -r '.blueprint.slug' package.json){{end}}" TAG_POST: '{{if .CLI_ARGS}}{{if ne .DOCKER_BASE_TAG .CLI_ARGS}}-{{.CLI_ARGS}}{{end}}{{end}}' log: error: Encountered error while generating compressed Docker image tar file start: Generating compressed Docker image tar file(s) success: Successfully generated compressed Docker image tar file(s) cmds: - | function zipUp() { docker save "{{.DOCKER_IMAGE}}:$1{{.TAG_POST}}" > "$1{{.TAG_POST}}.tar" gzip -f "$1{{.TAG_POST}}.tar" } zipUp "latest" & zipUp "slim" & wait slim:sizes:calculate: deps: - :install:software:jq vars: DOCKER_IMAGE_SLUG: sh: echo "{{if .CLI_ARGS}}{{.CLI_ARGS}}{{else}}$(jq -r '.blueprint.slug' package.json){{end}}" PREVIOUS_REGULAR_SIZE: sh: jq --arg slug '{{.DOCKER_IMAGE_SLUG}}' -r '.blueprint.dockerLatestSize[$slug]' package.json PREVIOUS_SLIM_SIZE: sh: jq --arg slug '{{.DOCKER_IMAGE_SLUG}}' -r '.blueprint.dockerSlimSize[$slug]' package.json REGULAR_SIZE: sh: stat {{if (eq OS "darwin")}}-f%z{{else}}-c%s{{end}} latest{{if .CLI_ARGS}}{{if ne .DOCKER_BASE_TAG .CLI_ARGS}}-{{.CLI_ARGS}}{{end}}{{end}}.tar.gz | numfmt --to iec SLIM_SIZE: sh: stat {{if (eq OS "darwin")}}-f%z{{else}}-c%s{{end}} slim{{if .CLI_ARGS}}{{if ne .DOCKER_BASE_TAG .CLI_ARGS}}-{{.CLI_ARGS}}{{end}}{{end}}.tar.gz | numfmt --to iec log: error: Failed to acquire / inject `:slim` image file size information into `package.json` blueprint data start: Injecting `:slim` image file size into `package.json` blueprint data cmds: - | TMP="$(mktemp)" jq --arg a '{{.SLIM_SIZE}}' --arg b '{{.REGULAR_SIZE}}' --arg slug '{{.DOCKER_IMAGE_SLUG}}' \ '.blueprint.dockerSlimSize[$slug] = $a | .blueprint.dockerLatestSize[$slug] = $b' package.json > "$TMP" mv "$TMP" package.json - task: slim:sizes:clean - task: :common:update:update status: - '[[ "{{.PREVIOUS_SLIM_SIZE}}" == "{{.SLIM_SIZE}}" ]]' - '[[ "{{.PREVIOUS_REGULAR_SIZE}}" == "{{.REGULAR_SIZE}}" ]]' slim:sizes:clean: cmds: - rm -f latest*.tar.gz - rm -f latest*.tar - rm -f slim*.tar.gz - rm -f slim*.tar status: - > ! test -n "$(find . -maxdepth 1 -name '*.tar.gz' -print -quit)"