From f9b5691c90978e05aec7e9c46ab308f71b6214e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Fern=C3=A1ndez=20Ponce?= <20102608+ezfepo@users.noreply.github.com> Date: Thu, 14 Jul 2022 13:56:23 -0300 Subject: [PATCH] [CONSUL-190] Support consul windows compilation in Docker (#14) --- .release/docker/docker-entrypoint-windows.sh | 82 ++++++++++++++++ Dockerfile-windows | 35 ++++++- .../Dockerfile-consul-dev-windows | 3 + .../Dockerfile-consul-dev-windows.sh | 14 +++ build-support-windows/build-images.sh | 32 ++++--- build-support-windows/docker.windows.md | 95 +++++++++++++------ .../docker/Consul-Dev-windows.compile.sh | 10 -- 7 files changed, 215 insertions(+), 56 deletions(-) create mode 100644 .release/docker/docker-entrypoint-windows.sh create mode 100644 build-support-windows/Dockerfile-consul-dev-windows create mode 100644 build-support-windows/Dockerfile-consul-dev-windows.sh delete mode 100644 build-support/docker/Consul-Dev-windows.compile.sh diff --git a/.release/docker/docker-entrypoint-windows.sh b/.release/docker/docker-entrypoint-windows.sh new file mode 100644 index 000000000000..776b8113ced3 --- /dev/null +++ b/.release/docker/docker-entrypoint-windows.sh @@ -0,0 +1,82 @@ +#!/usr/bin/dumb-init /bin/sh +set -e + +# Note above that we run dumb-init as PID 1 in order to reap zombie processes +# as well as forward signals to all processes in its session. Normally, sh +# wouldn't do either of these functions so we'd leak zombies as well as do +# unclean termination of all our sub-processes. +# As of docker 1.13, using docker run --init achieves the same outcome. + +# You can set CONSUL_BIND_INTERFACE to the name of the interface you'd like to +# bind to and this will look up the IP and pass the proper -bind= option along +# to Consul. +CONSUL_BIND= +if [ -n "$CONSUL_BIND_INTERFACE" ]; then + CONSUL_BIND_ADDRESS=$(ip -o -4 addr list $CONSUL_BIND_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) + if [ -z "$CONSUL_BIND_ADDRESS" ]; then + echo "Could not find IP for interface '$CONSUL_BIND_INTERFACE', exiting" + exit 1 + fi + + CONSUL_BIND="-bind=$CONSUL_BIND_ADDRESS" + echo "==> Found address '$CONSUL_BIND_ADDRESS' for interface '$CONSUL_BIND_INTERFACE', setting bind option..." +fi + +# You can set CONSUL_CLIENT_INTERFACE to the name of the interface you'd like to +# bind client intefaces (HTTP, DNS, and RPC) to and this will look up the IP and +# pass the proper -client= option along to Consul. +CONSUL_CLIENT= +if [ -n "$CONSUL_CLIENT_INTERFACE" ]; then + CONSUL_CLIENT_ADDRESS=$(ip -o -4 addr list $CONSUL_CLIENT_INTERFACE | head -n1 | awk '{print $4}' | cut -d/ -f1) + if [ -z "$CONSUL_CLIENT_ADDRESS" ]; then + echo "Could not find IP for interface '$CONSUL_CLIENT_INTERFACE', exiting" + exit 1 + fi + + CONSUL_CLIENT="-client=$CONSUL_CLIENT_ADDRESS" + echo "==> Found address '$CONSUL_CLIENT_ADDRESS' for interface '$CONSUL_CLIENT_INTERFACE', setting client option..." +fi + +# CONSUL_DATA_DIR is exposed as a volume for possible persistent storage. The +# CONSUL_CONFIG_DIR isn't exposed as a volume but you can compose additional +# config files in there if you use this image as a base, or use CONSUL_LOCAL_CONFIG +# below. +CONSUL_DATA_DIR=C:\\consul\\data +CONSUL_CONFIG_DIR=C:\\consul\\config + +# You can also set the CONSUL_LOCAL_CONFIG environemnt variable to pass some +# Consul configuration JSON without having to bind any volumes. +if [ -n "$CONSUL_LOCAL_CONFIG" ]; then + echo "$CONSUL_LOCAL_CONFIG" > "$CONSUL_CONFIG_DIR/local.json" +fi + +# If the user is trying to run Consul directly with some arguments, then +# pass them to Consul. +if [ "${1:0:1}" = '-' ]; then + set -- consul "$@" +fi + +# Look for Consul subcommands. +if [ "$1" = 'agent' ]; then + shift + set -- consul agent \ + -data-dir="$CONSUL_DATA_DIR" \ + -config-dir="$CONSUL_CONFIG_DIR" \ + $CONSUL_BIND \ + $CONSUL_CLIENT \ + "$@" +elif [ "$1" = 'version' ]; then + # This needs a special case because there's no help output. + set -- consul "$@" +elif consul --help "$1" 2>&1 | grep -q "consul $1"; then + # We can't use the return code to check for the existence of a subcommand, so + # we have to use grep to look for a pattern in the help output. + set -- consul "$@" +fi + +# NOTE: Unlike in the regular Consul Docker image, we don't have code here +# for changing data-dir directory ownership or using su-exec because OpenShift +# won't run this container as root and so we can't change data dir ownership, +# and there's no need to use su-exec. + +exec "$@" \ No newline at end of file diff --git a/Dockerfile-windows b/Dockerfile-windows index 5d371392c823..c6025612cba3 100644 --- a/Dockerfile-windows +++ b/Dockerfile-windows @@ -1,6 +1,16 @@ -ARG CONSUL_IMAGE_VERSION=1.12.0 FROM mcr.microsoft.com/windows/servercore:1809 +ENV VERSION=1.12.0 + +LABEL org.opencontainers.image.authors="Consul Team " \ + org.opencontainers.image.url="https://www.consul.io/" \ + org.opencontainers.image.documentation="https://www.consul.io/docs" \ + org.opencontainers.image.source="https://github.com/hashicorp/consul" \ + org.opencontainers.image.version=$VERSION \ + org.opencontainers.image.vendor="HashiCorp" \ + org.opencontainers.image.title="consul" \ + org.opencontainers.image.description="Consul is a datacenter runtime that provides service discovery, configuration, and orchestration." + RUN ["powershell", "Set-ExecutionPolicy", "Bypass", "-Scope", "Process", "-Force;"] RUN ["powershell", "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))"] @@ -10,14 +20,29 @@ RUN mkdir C:\\consul RUN mkdir C:\\consul\\data RUN mkdir C:\\consul\\config + +# Server RPC is used for communication between Consul clients and servers for internal +# request forwarding. EXPOSE 8300 + +# Serf LAN and WAN (WAN is used only by Consul servers) are used for gossip between +# Consul agents. LAN is within the datacenter and WAN is between just the Consul +# servers in all datacenters. EXPOSE 8301 8301/udp 8302 8302/udp -EXPOSE 8500 8600 8600/udp -ENV CONSUL_VERSION=1.12.0 -ENV CONSUL_URL=https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_windows_amd64.zip +# HTTP and DNS (both TCP and UDP) are the primary interfaces that applications +# use to interact with Consul. +EXPOSE 8500 8600 8600/udp +ENV CONSUL_URL=https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION}_windows_amd64.zip RUN curl %CONSUL_URL% -L -o consul.zip RUN tar -xf consul.zip -C consul - ENV PATH C:\\Program Files\\Git\\bin;C:\\consul;%PATH% + +COPY .release/docker/docker-entrypoint-windows.sh C:\\docker-entrypoint-windows.sh +ENTRYPOINT ["bash.exe", "docker-entrypoint-windows.sh"] + +# By default you'll get an insecure single-node development server that stores +# everything in RAM, exposes a web UI and HTTP endpoints, and bootstraps itself. +# Don't use this configuration for production. +CMD ["agent", "-dev", "-client", "0.0.0.0"] \ No newline at end of file diff --git a/build-support-windows/Dockerfile-consul-dev-windows b/build-support-windows/Dockerfile-consul-dev-windows new file mode 100644 index 000000000000..ab201971b225 --- /dev/null +++ b/build-support-windows/Dockerfile-consul-dev-windows @@ -0,0 +1,3 @@ +ARG CONSUL_IMAGE_VERSION=latest +FROM windows/consul:${CONSUL_IMAGE_VERSION} +COPY dist/ C:\\consul diff --git a/build-support-windows/Dockerfile-consul-dev-windows.sh b/build-support-windows/Dockerfile-consul-dev-windows.sh new file mode 100644 index 000000000000..8ddcc563616c --- /dev/null +++ b/build-support-windows/Dockerfile-consul-dev-windows.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +cd ../ +rm -rf dist + +export GOOS=windows GOARCH=amd64 +CONSUL_VERSION=1.12.0 +CONSUL_BUILDDATE=$(date +"%Y-%m-%dT%H:%M:%SZ") +GIT_IMPORT=github.com/hashicorp/consul/version +GOLDFLAGS=" -X $GIT_IMPORT.Version=$CONSUL_VERSION -X $GIT_IMPORT.VersionPrerelease=local -X $GIT_IMPORT.BuildDate=$CONSUL_BUILDDATE " + +go build -ldflags "$GOLDFLAGS" -o ./dist/ . + +docker build -t windows/consul-dev -f ./build-support-windows/Dockerfile-consul-dev-windows . diff --git a/build-support-windows/build-images.sh b/build-support-windows/build-images.sh index add42d0b84cf..25500dc291d0 100644 --- a/build-support-windows/build-images.sh +++ b/build-support-windows/build-images.sh @@ -7,23 +7,29 @@ export ENVOY_VERSION echo "Building Images" -# Pull Windows Nanoserver image -docker.exe pull mcr.microsoft.com/windows/nanoserver:1809 -# Re tag Pulled image -docker.exe tag mcr.microsoft.com/windows/nanoserver:1809 "${HASHICORP_DOCKER_PROXY}/windows/nanoserver" +# Build Windows Consul Image +docker build -t "windows/consul" -f ../Dockerfile-windows ../ -# Pull Envoy-Windows Image -docker.exe pull "envoyproxy/envoy-windows:v${ENVOY_VERSION}" -# Re tag Pulled image -docker.exe tag "envoyproxy/envoy-windows:v${ENVOY_VERSION}" "${HASHICORP_DOCKER_PROXY}/windows/envoy-windows:v${ENVOY_VERSION}" +# Build Windows Consul-Dev Image +./Dockerfile-consul-dev-windows.sh -# Build Fortio Windows Image -docker.exe build -t "${HASHICORP_DOCKER_PROXY}/windows/fortio" -f Dockerfile-fortio-windows . +# Pull Windows Nanoserver image +docker pull mcr.microsoft.com/windows/nanoserver:1809 +# Tag Windows Nanoserver image +docker tag mcr.microsoft.com/windows/nanoserver:1809 "${HASHICORP_DOCKER_PROXY}/windows/nanoserver" -# Build Socat-Windows Image -docker.exe build -t "${HASHICORP_DOCKER_PROXY}/windows/socat" -f Dockerfile-socat-windows . +# Pull Windows Envoy Image +docker pull "envoyproxy/envoy-windows:v${ENVOY_VERSION}" +# Tag Windows Envoy image +docker tag "envoyproxy/envoy-windows:v${ENVOY_VERSION}" "${HASHICORP_DOCKER_PROXY}/windows/envoy-windows:v${ENVOY_VERSION}" # Build Bats-Core-Windows Image -docker build -t "${HASHICORP_DOCKER_PROXY}/windows/bats:1.7.0" . -f Dockerfile-bats-core-windows +docker build -t "${HASHICORP_DOCKER_PROXY}/windows/bats:1.7.0" -f Dockerfile-bats-core-windows . + +# Build Windows Fortio Image +docker build -t "${HASHICORP_DOCKER_PROXY}/windows/fortio" -f Dockerfile-fortio-windows . + +# Build Windows Socat Image +docker build -t "${HASHICORP_DOCKER_PROXY}/windows/socat" -f Dockerfile-socat-windows . echo "Building Complete!" diff --git a/build-support-windows/docker.windows.md b/build-support-windows/docker.windows.md index cc2832feeb7b..03b1782d0637 100644 --- a/build-support-windows/docker.windows.md +++ b/build-support-windows/docker.windows.md @@ -3,22 +3,42 @@ ## Index - [About](#about-this-file) +- [Consul-windows](#consul-windows) +- [Dockerfile-bats-core-windows](#dockerfile-bats-core-windows) +- [Dockerfile-consul-dev-windows](#dockerfile-consul-dev-windows) - [Dockerfile-fortio-windows](#dockerfile-fortio-windows) - [Dockerfile-socat-windows](#dockerfile-socat-windows) -- [Dockerfile-bats-core-windows](#dockerfile-bats-core-windows) - [Build images](#build-images) ## About this File In this file you will find which Docker images that need to be pre-built to run the Envoy integration tests on Windows, as well as information on how to run each of these files individually for testing purposes. -## Dockerfile-fortio-windows +## Consul-windows -This file sole purpose is to build the custom Fortio image for Windows OS. To do this, the official [windows/nanoserver image](https://hub.docker.com/_/microsoft-windows-nanoserver) is used as base image. +The required Consul image is built from the "Dockerfile-windows" file located at the root of the project. +To do this, the official [windows/servercore image](https://hub.docker.com/_/microsoft-windows-servercore) is used as base image. +To build the image, use the following command: + +```shell +docker build -t windows/consul -f Dockerfile-windows . +``` + +You can test the built file by running the following command: + +```shell +docker run --rm -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8500:8500 -p 8600:8600 --name consul --hostname "consul-primary-server" --network-alias "consul-primary-server" windows/consul agent -dev -datacenter "primary" -grpc-port -1 -client "0.0.0.0" -bind "0.0.0.0" +``` +If everything works properly you should openning the browser and check the Consul UI running on: `http://localhost:8500` + + +## Dockerfile-bats-core-windows + +This file sole purpose is to build the custom Bats image for Windows OS. To do this, the official [windows/servercore image](https://hub.docker.com/_/microsoft-windows-servercore) is used as base image. To build this image you need to run the following command on your terminal: ```shell -docker build -t fortio . -f Dockerfile-fortio-windows +docker build -t bats-verify . -f Dockerfile-bats-windows ``` This is the same command used in run-tests.sh @@ -26,69 +46,88 @@ This is the same command used in run-tests.sh You can test the built file by running the following command: ```shell -docker run --rm -p 8080:8080 --name fortio fortio +docker run --rm --name bats-verify bats-verify ``` -If everything works properly you should openning the browser and check that the Fortio server running on: `http://localhost:8080/fortio` +If everything works properly you should see the help commands and available parameters about how to run Bats tests like is displayed below -## Dockerfile-socat-windows +```shell +$ docker run --rm --name bats-verify bats-verify +Usage: bats [OPTIONS] + bats [-h | -v] -The alpine:socat image was replaced by a windows core image to which a precompiled version of Socat was installed. + is the path to a Bats test file, or the path to a directory + containing Bats test files (ending with ".bats") +``` -The windows base used was: `mcr.microsoft.com/windows/servercore:1809` +## Dockerfile-consul-dev-windows -The compiled windows version of Socat can be found in the repository [https://github.com/tech128/socat-1.7.3.0-windows](https://github.com/tech128/socat-1.7.3.0-windows) +The Consul-dev custom image deployed in the "Dockerfile-consul-dev-windows" DockerFile is generated by the sh script of the same name. +When executing it, the compilation of Consul is carried out and it is saved in the _"dist"_ directory, this file is then copied to a container created from the _"windows/consul"_ image. +It is necessary that the _"windows/consul"_ image has been built first. To build this image you need to run the following command on your terminal: ```shell -docker build -t socat -f Dockerfile-socat-windows . +./Dockerfile-consul-dev-windows.sh ``` You can test the built file by running the following command: ```shell -docker run --rm --name socat socat +docker run --rm -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8500:8500 -p 8600:8600 --name consul-dev --hostname "consul-primary-server" --network-alias "consul-primary-server" windows/consul-dev agent -dev -datacenter "primary" -grpc-port -1 -client "0.0.0.0" -bind "0.0.0.0" ``` +If everything works properly you should openning the browser and check the Consul UI running on: `http://localhost:8500` -If everything works properly you should get the following output: +## Dockerfile-fortio-windows + +This file sole purpose is to build the custom Fortio image for Windows OS. To do this, the official [windows/nanoserver image](https://hub.docker.com/_/microsoft-windows-nanoserver) is used as base image. +To build this image you need to run the following command on your terminal: ```shell -20XX/XX/XX XX:XX:XX socat[1292] E exactly 2 addresses required (there are 0); use option "-h" for help +docker build -t fortio . -f Dockerfile-fortio-windows ``` -## Dockerfile-bats-core-windows +This is the same command used in run-tests.sh -This file sole purpose is to build the custom Bats image for Windows OS. To do this, the official [windows/servercore image](https://hub.docker.com/_/microsoft-windows-servercore) is used as base image. -To build this image you need to run the following command on your terminal: +You can test the built file by running the following command: ```shell -docker build -t bats-verify . -f Dockerfile-bats-windows +docker run --rm -p 8080:8080 --name fortio fortio ``` -This is the same command used in run-tests.sh +If everything works properly you should openning the browser and check that the Fortio server running on: `http://localhost:8080/fortio` -You can test the built file by running the following command: +## Dockerfile-socat-windows + +The alpine:socat image was replaced by a windows core image to which a precompiled version of Socat was installed. + +The windows base used was: `mcr.microsoft.com/windows/servercore:1809` + +The compiled windows version of Socat can be found in the repository [https://github.com/tech128/socat-1.7.3.0-windows](https://github.com/tech128/socat-1.7.3.0-windows) + +To build this image you need to run the following command on your terminal: ```shell -docker run --rm --name bats-verify bats-verify +docker build -t socat -f Dockerfile-socat-windows . ``` -If everything works properly you should see the help commands and available parameters about how to run Bats tests like is displayed below +You can test the built file by running the following command: ```shell -$ docker run --rm --name bats-verify bats-verify -Usage: bats [OPTIONS] - bats [-h | -v] +docker run --rm --name socat socat +``` - is the path to a Bats test file, or the path to a directory - containing Bats test files (ending with ".bats") +If everything works properly you should get the following output: + +```shell +20XX/XX/XX XX:XX:XX socat[1292] E exactly 2 addresses required (there are 0); use option "-h" for help ``` ## Build images To build the images, it is necessary to open a Git bash terminal and run -``` +```shell ./build-images.sh ``` diff --git a/build-support/docker/Consul-Dev-windows.compile.sh b/build-support/docker/Consul-Dev-windows.compile.sh deleted file mode 100644 index 3aa6ecddbf64..000000000000 --- a/build-support/docker/Consul-Dev-windows.compile.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -export GOOS=windows GOARCH=amd64 - -GIT_COMMIT=$(git rev-parse --short HEAD) -GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) -GIT_IMPORT=github.com/hashicorp/consul/version -GIT_DATE=$(../build-support/scripts/build-date.sh) -GOLDFLAGS=" -X $GIT_IMPORT.GitCommit=$GIT_COMMIT$GIT_DIRTY -X $GIT_IMPORT.BuildDate=$GIT_DATE " - -go build -ldflags "$GOLDFLAGS" -o ../../dist/ . \ No newline at end of file