Build: Unified dockerfile for all builds (#59173)

* unified dockerfile for all builds

* update builder

* include docker commands and output in logs

* quiet docker build

* quiet gsutil
This commit is contained in:
Dan Cech
2022-11-28 16:18:53 -05:00
committed by GitHub
parent 3377575788
commit 7436872dab
6 changed files with 65 additions and 189 deletions

View File

@@ -1,16 +1,12 @@
######################## IMPORTANT ########################
#
# There are 2 Dockerfiles which must be kept in sync:
#
# - Dockerfile
# - packaging/docker/Dockerfile
#
###########################################################
# syntax=docker/dockerfile:1
ARG BASE_IMAGE=alpine:3.15
ARG JS_IMAGE=node:16-alpine3.15
ARG GO_IMAGE=golang:1.19.3-alpine3.15
ARG GO_SRC=go-builder
ARG JS_SRC=js-builder
FROM ${JS_IMAGE} as js-builder
ENV NODE_OPTIONS=--max_old_space_size=8000
@@ -56,9 +52,25 @@ COPY public/app/plugins public/app/plugins
COPY public/api-spec.json public/api-spec.json
COPY pkg pkg
COPY scripts scripts
COPY conf conf
RUN make build-go
FROM ${BASE_IMAGE} as tgz-builder
WORKDIR /tmp/grafana
ARG GRAFANA_TGZ="grafana-latest.linux-x64-musl.tar.gz"
COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz
# add -v to make tar print every file it extracts
RUN tar x -z -f /tmp/grafana.tar.gz --strip-components=1
# helpers for COPY --from
FROM ${GO_SRC} as go-src
FROM ${JS_SRC} as js-src
# Final stage
FROM ${BASE_IMAGE}
@@ -106,7 +118,7 @@ RUN if grep -i -q alpine /etc/issue && [ `arch` = "x86_64" ]; then \
rm -f /etc/ld.so.cache; \
fi
COPY conf ./conf
COPY --from=go-src /tmp/grafana/conf ./conf
RUN if [ ! $(getent group "$GF_GID") ]; then \
if grep -i -q alpine /etc/issue; then \
@@ -136,12 +148,14 @@ RUN if [ ! $(getent group "$GF_GID") ]; then \
chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
COPY --from=go-builder /tmp/grafana/bin/*/grafana-server /tmp/grafana/bin/*/grafana-cli /tmp/grafana/bin/*/grafana ./bin/
COPY --from=js-builder /tmp/grafana/public ./public
COPY --from=go-src /tmp/grafana/bin/grafana* /tmp/grafana/bin/*/grafana* ./bin/
COPY --from=js-src /tmp/grafana/public ./public
EXPOSE 3000
COPY ./packaging/docker/run.sh /run.sh
ARG RUN_SH=./packaging/docker/run.sh
COPY ${RUN_SH} /run.sh
USER "$GF_UID"
ENTRYPOINT [ "/run.sh" ]

View File

@@ -158,11 +158,13 @@ shellcheck: $(SH_FILES) ## Run checks for shell scripts.
build-docker-full: ## Build Docker image for development.
@echo "build docker container"
DOCKER_BUILDKIT=1 \
docker build \
--tag grafana/grafana:dev .
build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development.
@echo "build docker container"
DOCKER_BUILDKIT=1 \
docker build \
--build-arg BASE_IMAGE=ubuntu:20.04 \
--build-arg GO_IMAGE=golang:1.19.3 \

View File

@@ -1,113 +0,0 @@
######################## IMPORTANT ########################
#
# There are 2 Dockerfiles which must be kept in sync:
#
# - Dockerfile
# - packaging/docker/Dockerfile
#
###########################################################
ARG BASE_IMAGE=alpine:3.15
FROM ${BASE_IMAGE} as tgz-builder
WORKDIR /tmp/grafana
ARG GRAFANA_TGZ="grafana-latest.linux-x64-musl.tar.gz"
# Make sure we have Gnu tar
RUN if grep -i -q alpine /etc/issue; then \
apk add --no-cache tar; \
fi
COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz
# Change to tar xfzv to make tar print every file it extracts
RUN tar xzf /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana
# Final stage
FROM ${BASE_IMAGE}
LABEL maintainer="Grafana Labs <hello@grafana.com>"
ARG GF_UID="472"
ARG GF_GID="0"
ENV PATH="/usr/share/grafana/bin:$PATH" \
GF_PATHS_CONFIG="/etc/grafana/grafana.ini" \
GF_PATHS_DATA="/var/lib/grafana" \
GF_PATHS_HOME="/usr/share/grafana" \
GF_PATHS_LOGS="/var/log/grafana" \
GF_PATHS_PLUGINS="/var/lib/grafana/plugins" \
GF_PATHS_PROVISIONING="/etc/grafana/provisioning"
WORKDIR $GF_PATHS_HOME
# Install dependencies
RUN if grep -i -q alpine /etc/issue; then \
apk add --no-cache ca-certificates bash tzdata musl-utils && \
apk info -vv | sort; \
elif grep -i -q ubuntu /etc/issue; then \
DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y ca-certificates curl tzdata && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*; \
else \
echo 'ERROR: Unsupported base image' && /bin/false; \
fi
# glibc support for alpine x86_64 only
RUN if grep -i -q alpine /etc/issue && [ `arch` = "x86_64" ]; then \
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-2.35-r0.apk \
-O /tmp/glibc-2.35-r0.apk && \
wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-bin-2.35-r0.apk \
-O /tmp/glibc-bin-2.35-r0.apk && \
apk add --no-cache --allow-untrusted /tmp/glibc-2.35-r0.apk /tmp/glibc-bin-2.35-r0.apk && \
rm -f /lib64/ld-linux-x86-64.so.2 && \
ln -s /usr/glibc-compat/lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 && \
rm -f /tmp/glibc-2.35-r0.apk && \
rm -f /tmp/glibc-bin-2.35-r0.apk && \
rm -f /lib/ld-linux-x86-64.so.2 && \
rm -f /etc/ld.so.cache; \
fi
COPY --from=tgz-builder /tmp/grafana/conf ./conf
RUN if [ ! $(getent group "$GF_GID") ]; then \
if grep -i -q alpine /etc/issue; then \
addgroup -S -g $GF_GID grafana; \
else \
addgroup --system --gid $GF_GID grafana; \
fi; \
fi && \
GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \
mkdir -p "$GF_PATHS_HOME/.aws" && \
if grep -i -q alpine /etc/issue; then \
adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana; \
else \
adduser --system --uid $GF_UID --ingroup "$GF_GID_NAME" grafana; \
fi && \
mkdir -p "$GF_PATHS_PROVISIONING/datasources" \
"$GF_PATHS_PROVISIONING/dashboards" \
"$GF_PATHS_PROVISIONING/notifiers" \
"$GF_PATHS_PROVISIONING/plugins" \
"$GF_PATHS_PROVISIONING/access-control" \
"$GF_PATHS_PROVISIONING/alerting" \
"$GF_PATHS_LOGS" \
"$GF_PATHS_PLUGINS" \
"$GF_PATHS_DATA" && \
cp conf/sample.ini "$GF_PATHS_CONFIG" && \
cp conf/ldap.toml /etc/grafana/ldap.toml && \
chown -R "grafana:$GF_GID_NAME" "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING" && \
chmod -R 777 "$GF_PATHS_DATA" "$GF_PATHS_HOME/.aws" "$GF_PATHS_LOGS" "$GF_PATHS_PLUGINS" "$GF_PATHS_PROVISIONING"
COPY --from=tgz-builder /tmp/grafana/bin/grafana-server /tmp/grafana/bin/grafana-cli ./bin/
COPY --from=tgz-builder /tmp/grafana/public ./public
EXPOSE 3000
COPY ./run.sh /run.sh
USER "$GF_UID"
ENTRYPOINT [ "/run.sh" ]

View File

@@ -1,51 +0,0 @@
#!/bin/sh
set -e
UBUNTU_BASE=0
TAG_SUFFIX=""
while [ "$1" != "" ]; do
case "$1" in
"--ubuntu")
UBUNTU_BASE=1
TAG_SUFFIX="-ubuntu"
echo "Ubuntu base image enabled"
shift
;;
* )
# unknown param causes args to be passed through to $@
break
;;
esac
done
_raw_grafana_tag=$1
_docker_repo=${2:-grafana/grafana-enterprise}
if echo "$_raw_grafana_tag" | grep -q "^v"; then
_grafana_tag=$(echo "${_raw_grafana_tag}" | cut -d "v" -f 2)
elif echo "$_raw_grafana_tag" | grep -q "^main-"; then
_grafana_tag="main"
else
_grafana_tag="${_raw_grafana_tag}"
fi
echo "Building and deploying ${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}"
docker build \
--tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" \
--no-cache=true \
.
docker push "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}"
if echo "$_raw_grafana_tag" | grep -q "^v" && echo "$_raw_grafana_tag" | grep -qv "beta"; then
docker tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" "${_docker_repo}:latest${TAG_SUFFIX}"
docker push "${_docker_repo}:latest${TAG_SUFFIX}"
fi
if echo "${_raw_grafana_tag}" | grep -q "^main-" && [ ${UBUNTU_BASE} = "1" ]; then
docker tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" "grafana/grafana-enterprise-dev:${_raw_grafana_tag}"
docker push "grafana/grafana-enterprise-dev:${_raw_grafana_tag}"
fi

View File

@@ -68,11 +68,16 @@ docker_build () {
grafana_tgz=${GRAFANA_TGZ:-"grafana-latest.linux-${arch}${libc}.tar.gz"}
tag="${_docker_repo}${repo_arch}:${_grafana_version}${TAG_SUFFIX}"
DOCKER_BUILDKIT=1 \
docker build \
--build-arg BASE_IMAGE=${base_image} \
--build-arg GRAFANA_TGZ=${grafana_tgz} \
--build-arg GO_SRC=tgz-builder \
--build-arg JS_SRC=tgz-builder \
--build-arg RUN_SH=./run.sh \
--tag "${tag}" \
--no-cache=true \
--file ../../Dockerfile \
.
}

View File

@@ -116,33 +116,49 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use
tags = append(tags, tag)
args := []string{
"build", "--build-arg", fmt.Sprintf("BASE_IMAGE=%s", baseImage),
"--build-arg", fmt.Sprintf("GRAFANA_TGZ=%s", archive), "--tag", tag, "--no-cache",
"build",
"-q",
"--build-arg", fmt.Sprintf("BASE_IMAGE=%s", baseImage),
"--build-arg", fmt.Sprintf("GRAFANA_TGZ=%s", archive),
"--build-arg", "GO_SRC=tgz-builder",
"--build-arg", "JS_SRC=tgz-builder",
"--build-arg", "RUN_SH=./run.sh",
"--tag", tag,
"--no-cache",
"--file", "../../Dockerfile",
".",
}
log.Printf("Running Docker: docker %s", strings.Join(args, " "))
//nolint:gosec
cmd := exec.Command("docker", args...)
cmd.Dir = buildDir
cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled")
if output, err := cmd.CombinedOutput(); err != nil {
return []string{}, fmt.Errorf("building Docker image failed: %w\n%s", err, output)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled", "DOCKER_BUILDKIT=1")
log.Printf("Running Docker: DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=1 %s", cmd)
if err := cmd.Run(); err != nil {
return []string{}, fmt.Errorf("building Docker image failed: %w", err)
}
if shouldSave {
imageFile := fmt.Sprintf("%s-%s%s-%s.img", imageFileBase, version, tagSuffix, arch)
//nolint:gosec
cmd = exec.Command("docker", "save", tag, "-o", imageFile)
cmd.Dir = buildDir
if output, err := cmd.CombinedOutput(); err != nil {
return []string{}, fmt.Errorf("saving Docker image failed: %w\n%s", err, output)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("Running Docker: %s", cmd)
if err := cmd.Run(); err != nil {
return []string{}, fmt.Errorf("saving Docker image failed: %w", err)
}
gcsURL := fmt.Sprintf("gs://grafana-prerelease/artifacts/docker/%s/%s", version, imageFile)
//nolint:gosec
cmd = exec.Command("gsutil", "cp", imageFile, gcsURL)
cmd = exec.Command("gsutil", "-q", "cp", imageFile, gcsURL)
cmd.Dir = buildDir
if output, err := cmd.CombinedOutput(); err != nil {
return []string{}, fmt.Errorf("storing Docker image failed: %w\n%s", err, output)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("Running gsutil: %s", cmd)
if err := cmd.Run(); err != nil {
return []string{}, fmt.Errorf("storing Docker image failed: %w", err)
}
log.Printf("Docker image %s stored to grafana-prerelease GCS bucket", imageFile)
}
@@ -152,8 +168,11 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use
//nolint:gosec
cmd = exec.Command("docker", "tag", tag, additionalTag)
cmd.Dir = buildDir
if output, err := cmd.CombinedOutput(); err != nil {
return []string{}, fmt.Errorf("tagging Docker image failed: %w\n%s", err, output)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Printf("Running Docker: %s", cmd)
if err := cmd.Run(); err != nil {
return []string{}, fmt.Errorf("tagging Docker image failed: %w", err)
}
tags = append(tags, additionalTag)
}