Add docker dev build targets (#9426)

* Add docker dev build target

* Update scripts/docker/Dockerfile

Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com>

* Add multi-stage build

* Add comment about multi-stage

* Add docker-dev-ui

Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com>
This commit is contained in:
Jason O'Donnell 2020-07-20 14:11:34 -04:00 committed by GitHub
parent d777708fde
commit bbec78261b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 266 additions and 0 deletions

View file

@ -52,6 +52,14 @@ dev-ui-mem: assetcheck dev-ui
dev-dynamic-mem: BUILD_TAGS+=memprofiler
dev-dynamic-mem: dev-dynamic
# Creates a Docker image by adding the compiled linux/amd64 binary found in ./bin.
# The resulting image is tagged "vault:dev".
docker-dev: prep
docker build -f scripts/docker/Dockerfile -t vault:dev .
docker-dev-ui: prep
docker build -f scripts/docker/Dockerfile.ui -t vault:dev-ui .
# test runs the unit tests and vets the code
test: prep
@CGO_ENABLED=$(CGO_ENABLED) \

64
scripts/docker/Dockerfile Normal file
View file

@ -0,0 +1,64 @@
# Multi-stage builder to avoid polluting users environment with wrong
# architecture binaries. Since this binary is used in an alpine container,
# we're explicitly compiling for 'linux/amd64'
ARG VERSION=1.13.10
FROM golang:${VERSION} AS builder
ARG CGO_ENABLED=0
ARG BUILD_TAGS
WORKDIR /go/src/github.com/hashicorp/vault
COPY . .
RUN make bootstrap \
&& CGO_ENABLED=$CGO_ENABLED BUILD_TAGS='$BUILD_TAGS' VAULT_DEV_BUILD=1 XC_OSARCH='linux/amd64' sh -c "'./scripts/build.sh'"
# Docker Image
FROM alpine:3.10
# Create a vault user and group first so the IDs get set the same way,
# even as the rest of this may change over time.
RUN addgroup vault && \
adduser -S -G vault vault
# Set up certificates, our base tools, and Vault.
RUN set -eux; \
apk add --no-cache ca-certificates libcap su-exec dumb-init tzdata
COPY --from=builder /go/bin/vault /bin/vault
# /vault/logs is made available to use as a location to store audit logs, if
# desired; /vault/file is made available to use as a location with the file
# storage backend, if desired; the server will be started with /vault/config as
# the configuration directory so you can add additional config files in that
# location.
RUN mkdir -p /vault/logs && \
mkdir -p /vault/file && \
mkdir -p /vault/config && \
chown -R vault:vault /vault
# Expose the logs directory as a volume since there's potentially long-running
# state in there
VOLUME /vault/logs
# Expose the file directory as a volume since there's potentially long-running
# state in there
VOLUME /vault/file
# 8200/tcp is the primary interface that applications use to interact with
# Vault.
EXPOSE 8200
# The entry point script uses dumb-init as the top-level process to reap any
# zombie processes created by Vault sub-processes.
#
# For production derivatives of this container, you should add the IPC_LOCK
# capability so that Vault can mlock memory.
COPY ./scripts/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
# By default you'll get a single-node development server that stores everything
# in RAM and bootstraps itself. Don't use this configuration for production.
CMD ["server", "-dev"]

View file

@ -0,0 +1,90 @@
# Multi-stage builder to avoid polluting users environment with wrong
# architecture binaries. Since this binary is used in an alpine container,
# we're explicitly compiling for 'linux/amd64'
FROM debian:buster AS builder
ARG VERSION=1.13.10
ARG CGO_ENABLED=0
ARG BUILD_TAGS
ENV JOBS=2
RUN apt-get update -y && apt-get install --no-install-recommends -y -q \
curl \
zip \
build-essential \
gcc-multilib \
g++-multilib \
ca-certificates \
git mercurial bzr \
gnupg \
libltdl-dev \
libltdl7
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -y && apt-get install -y -q nodejs yarn
RUN rm -rf /var/lib/apt/lists/*
RUN mkdir /goroot && mkdir /go
RUN curl https://storage.googleapis.com/golang/go${VERSION}.linux-amd64.tar.gz \
| tar xvzf - -C /goroot --strip-components=1
ENV GOPATH /go
ENV GOROOT /goroot
ENV PATH $GOROOT/bin:$GOPATH/bin:$PATH
WORKDIR /go/src/github.com/hashicorp/vault
COPY . .
RUN make bootstrap static-dist \
&& CGO_ENABLED=$CGO_ENABLED BUILD_TAGS='$BUILD_TAGS ui' VAULT_DEV_BUILD=1 XC_OSARCH='linux/amd64' sh -c "'./scripts/build.sh'"
# Docker Image
FROM alpine:3.10
# Create a vault user and group first so the IDs get set the same way,
# even as the rest of this may change over time.
RUN addgroup vault && \
adduser -S -G vault vault
# Set up certificates, our base tools, and Vault.
RUN set -eux; \
apk add --no-cache ca-certificates libcap su-exec dumb-init tzdata
COPY --from=builder /go/bin/vault /bin/vault
# /vault/logs is made available to use as a location to store audit logs, if
# desired; /vault/file is made available to use as a location with the file
# storage backend, if desired; the server will be started with /vault/config as
# the configuration directory so you can add additional config files in that
# location.
RUN mkdir -p /vault/logs && \
mkdir -p /vault/file && \
mkdir -p /vault/config && \
chown -R vault:vault /vault
# Expose the logs directory as a volume since there's potentially long-running
# state in there
VOLUME /vault/logs
# Expose the file directory as a volume since there's potentially long-running
# state in there
VOLUME /vault/file
# 8200/tcp is the primary interface that applications use to interact with
# Vault.
EXPOSE 8200
# The entry point script uses dumb-init as the top-level process to reap any
# zombie processes created by Vault sub-processes.
#
# For production derivatives of this container, you should add the IPC_LOCK
# capability so that Vault can mlock memory.
COPY ./scripts/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
# By default you'll get a single-node development server that stores everything
# in RAM and bootstraps itself. Don't use this configuration for production.
CMD ["server", "-dev"]

View file

@ -0,0 +1,104 @@
#!/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.
# Prevent core dumps
ulimit -c 0
# Allow setting VAULT_REDIRECT_ADDR and VAULT_CLUSTER_ADDR using an interface
# name instead of an IP address. The interface name is specified using
# VAULT_REDIRECT_INTERFACE and VAULT_CLUSTER_INTERFACE environment variables. If
# VAULT_*_ADDR is also set, the resulting URI will combine the protocol and port
# number with the IP of the named interface.
get_addr () {
local if_name=$1
local uri_template=$2
ip addr show dev $if_name | awk -v uri=$uri_template '/\s*inet\s/ { \
ip=gensub(/(.+)\/.+/, "\\1", "g", $2); \
print gensub(/^(.+:\/\/).+(:.+)$/, "\\1" ip "\\2", "g", uri); \
exit}'
}
if [ -n "$VAULT_REDIRECT_INTERFACE" ]; then
export VAULT_REDIRECT_ADDR=$(get_addr $VAULT_REDIRECT_INTERFACE ${VAULT_REDIRECT_ADDR:-"http://0.0.0.0:8200"})
echo "Using $VAULT_REDIRECT_INTERFACE for VAULT_REDIRECT_ADDR: $VAULT_REDIRECT_ADDR"
fi
if [ -n "$VAULT_CLUSTER_INTERFACE" ]; then
export VAULT_CLUSTER_ADDR=$(get_addr $VAULT_CLUSTER_INTERFACE ${VAULT_CLUSTER_ADDR:-"https://0.0.0.0:8201"})
echo "Using $VAULT_CLUSTER_INTERFACE for VAULT_CLUSTER_ADDR: $VAULT_CLUSTER_ADDR"
fi
# VAULT_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
# VAULT_LOCAL_CONFIG below.
VAULT_CONFIG_DIR=/vault/config
# You can also set the VAULT_LOCAL_CONFIG environment variable to pass some
# Vault configuration JSON without having to bind any volumes.
if [ -n "$VAULT_LOCAL_CONFIG" ]; then
echo "$VAULT_LOCAL_CONFIG" > "$VAULT_CONFIG_DIR/local.json"
fi
# If the user is trying to run Vault directly with some arguments, then
# pass them to Vault.
if [ "${1:0:1}" = '-' ]; then
set -- vault "$@"
fi
# Look for Vault subcommands.
if [ "$1" = 'server' ]; then
shift
set -- vault server \
-config="$VAULT_CONFIG_DIR" \
-dev-root-token-id="$VAULT_DEV_ROOT_TOKEN_ID" \
-dev-listen-address="${VAULT_DEV_LISTEN_ADDRESS:-"0.0.0.0:8200"}" \
"$@"
elif [ "$1" = 'version' ]; then
# This needs a special case because there's no help output.
set -- vault "$@"
elif vault --help "$1" 2>&1 | grep -q "vault $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 -- vault "$@"
fi
# If we are running Vault, make sure it executes as the proper user.
if [ "$1" = 'vault' ]; then
if [ -z "$SKIP_CHOWN" ]; then
# If the config dir is bind mounted then chown it
if [ "$(stat -c %u /vault/config)" != "$(id -u vault)" ]; then
chown -R vault:vault /vault/config || echo "Could not chown /vault/config (may not have appropriate permissions)"
fi
# If the logs dir is bind mounted then chown it
if [ "$(stat -c %u /vault/logs)" != "$(id -u vault)" ]; then
chown -R vault:vault /vault/logs
fi
# If the file dir is bind mounted then chown it
if [ "$(stat -c %u /vault/file)" != "$(id -u vault)" ]; then
chown -R vault:vault /vault/file
fi
fi
if [ -z "$SKIP_SETCAP" ]; then
# Allow mlock to avoid swapping Vault memory to disk
setcap cap_ipc_lock=+ep $(readlink -f $(which vault))
# In the case vault has been started in a container without IPC_LOCK privileges
if ! vault -version 1>/dev/null 2>/dev/null; then
>&2 echo "Couldn't start vault with IPC_LOCK. Disabling IPC_LOCK, please use --privileged or --cap-add IPC_LOCK"
setcap cap_ipc_lock=-ep $(readlink -f $(which vault))
fi
fi
if [ "$(id -u)" = '0' ]; then
set -- su-exec vault "$@"
fi
fi
exec "$@"