diff --git a/.dockerignore b/.dockerignore index 7ed8d01615e..1df915d2461 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,7 +2,6 @@ .dockerignore .git .gitignore -.github .vscode bin data* diff --git a/.github/pr-commands.json b/.github/pr-commands.json index addfca786bf..544581a0a7c 100644 --- a/.github/pr-commands.json +++ b/.github/pr-commands.json @@ -66,8 +66,7 @@ "scripts/build/**/*", "scripts/*.sh", "Makefile", - "Dockerfile", - "Dockerfile.ubuntu" + "Dockerfile" ], "action": "updateLabel", "addLabel": "type/build-packaging" diff --git a/Dockerfile b/Dockerfile index 5a1f9a9feaa..f294552b8d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,94 +1,166 @@ -FROM node:16-alpine3.15 as js-builder +# syntax=docker/dockerfile:1 + +ARG BASE_IMAGE=alpine:3.15 +ARG JS_IMAGE=node:16-alpine3.15 +ARG GO_IMAGE=golang:1.19.4-alpine3.17 + +ARG GO_SRC=go-builder +ARG JS_SRC=js-builder + +FROM ${JS_IMAGE} as js-builder ENV NODE_OPTIONS=--max_old_space_size=8000 -WORKDIR /grafana +WORKDIR /tmp/grafana COPY package.json yarn.lock .yarnrc.yml ./ COPY .yarn .yarn COPY packages packages COPY plugins-bundled plugins-bundled +RUN apk add --update python3 make g++\ + && rm -rf /var/cache/apk/* + RUN yarn install COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./ COPY public public -COPY tools tools COPY scripts scripts COPY emails emails ENV NODE_ENV production RUN yarn build -FROM golang:1.19.4-alpine3.17 as go-builder +FROM ${GO_IMAGE} as go-builder -RUN apk add --no-cache gcc g++ make +# Install build dependencies +RUN if grep -i -q alpine /etc/issue; then \ + apk add --no-cache gcc g++ make binutils-gold; \ + fi -WORKDIR /grafana +WORKDIR /tmp/grafana -COPY go.mod go.sum embed.go Makefile build.go package.json ./ +COPY go.* ./ +COPY .bingo .bingo + +RUN go mod download && \ + go install github.com/bwplotka/bingo@latest && \ + bingo get + +COPY embed.go Makefile build.go package.json ./ +COPY cue.mod cue.mod +COPY kinds kinds +COPY local local COPY packages/grafana-schema packages/grafana-schema COPY public/app/plugins public/app/plugins COPY public/api-spec.json public/api-spec.json COPY pkg pkg COPY scripts scripts -COPY cue.mod cue.mod -COPY .bingo .bingo +COPY conf conf +COPY .github .github -RUN go mod verify RUN make build-go -# Final stage -FROM alpine:3.15.6 +FROM ${BASE_IMAGE} as tgz-builder -LABEL maintainer="Grafana team " +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} + +LABEL maintainer="Grafana Labs " 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" + 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 -RUN apk add --no-cache ca-certificates bash tzdata musl-utils -RUN apk info -vv | sort +# 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 -COPY conf ./conf +# 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=go-src /tmp/grafana/conf ./conf RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup -S -g $GF_GID grafana; \ - fi + 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" -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana && \ - 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 "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/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=go-builder /grafana/bin/*/grafana-server /grafana/bin/*/grafana-cli /grafana/bin/*/grafana ./bin/ -COPY --from=js-builder /grafana/public ./public -COPY --from=js-builder /grafana/tools ./tools +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 -USER grafana +COPY ${RUN_SH} /run.sh + +USER "$GF_UID" ENTRYPOINT [ "/run.sh" ] diff --git a/Makefile b/Makefile index efa1d370109..55eb23acc3f 100644 --- a/Makefile +++ b/Makefile @@ -152,12 +152,17 @@ shellcheck: $(SH_FILES) ## Run checks for shell scripts. build-docker-full: ## Build Docker image for development. @echo "build docker container" - docker build --tag grafana/grafana:dev . + 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 build --tag grafana/grafana:dev-ubuntu -f ./Dockerfile.ubuntu . - + DOCKER_BUILDKIT=1 \ + docker build \ + --build-arg BASE_IMAGE=ubuntu:20.04 \ + --build-arg GO_IMAGE=golang:1.19.4 \ + --tag grafana/grafana:dev-ubuntu . ##@ Services diff --git a/docs/sources/setup-grafana/installation/docker.md b/docs/sources/setup-grafana/installation/docker.md index 5fb7a8b3dbb..eadf40d6ba2 100644 --- a/docs/sources/setup-grafana/installation/docker.md +++ b/docs/sources/setup-grafana/installation/docker.md @@ -112,7 +112,20 @@ docker run -d \ You can build your own customized image that includes plugins. This saves time if you are creating multiple images and you want them all to have the same plugins installed on build. -In the [Grafana GitHub repository](https://github.com/grafana/grafana) there is a folder called `packaging/docker/custom/`, which includes two Dockerfiles, `Dockerfile` and `ubuntu.Dockerfile`, that can be used to build a custom Grafana image. It accepts `GRAFANA_VERSION`, `GF_INSTALL_PLUGINS`, and `GF_INSTALL_IMAGE_RENDERER_PLUGIN` as build arguments. +In the [Grafana GitHub repository](https://github.com/grafana/grafana) there is a folder called `packaging/docker/custom/`, which includes a Dockerfile that can be used to build a custom Grafana image. It accepts `GRAFANA_VERSION`, `GF_INSTALL_PLUGINS`, and `GF_INSTALL_IMAGE_RENDERER_PLUGIN` as build arguments. + +The `GRAFANA_VERSION` build argument must be a valid `grafana/grafana` docker image tag. By default, this builds an Alpine-based image. To build an Ubuntu-based image, append `-ubuntu` to the `GRAFANA_VERSION` build argument (available in Grafana v6.5 and later). + +The following example shows you how to build and run a custom Grafana Docker image based on the latest official Ubuntu-based Grafana Docker image: + +```bash +cd packaging/docker/custom +docker build \ + --build-arg "GRAFANA_VERSION=latest-ubuntu" \ + -t grafana-custom . + +docker run -d -p 3000:3000 --name=grafana grafana-custom +``` ### Build with pre-installed plugins @@ -125,7 +138,7 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` @@ -139,13 +152,11 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_PLUGINS=http://plugin-domain.com/my-custom-plugin.zip;custom-plugin,grafana-clock-panel" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` -Replace `Dockerfile` in above example with `ubuntu.Dockerfile` to build a custom Ubuntu based image (Grafana v6.5+). - ### Build with Grafana Image Renderer plugin pre-installed > Only available in Grafana v6.5 and later. This is experimental. @@ -159,13 +170,11 @@ cd packaging/docker/custom docker build \ --build-arg "GRAFANA_VERSION=latest" \ --build-arg "GF_INSTALL_IMAGE_RENDERER_PLUGIN=true" \ - -t grafana-custom -f Dockerfile . + -t grafana-custom . docker run -d -p 3000:3000 --name=grafana grafana-custom ``` -Replace `Dockerfile` in above example with `ubuntu.Dockerfile` to build a custom Ubuntu-based image (Grafana v6.5+). - ## Migrate from previous Docker containers versions This section contains important information if you want to migrate from previous Grafana container versions to a more current one. diff --git a/packaging/docker/Dockerfile b/packaging/docker/Dockerfile deleted file mode 100644 index 7acefcc0b5a..00000000000 --- a/packaging/docker/Dockerfile +++ /dev/null @@ -1,75 +0,0 @@ -ARG BASE_IMAGE=alpine:3.15 -FROM ${BASE_IMAGE} - -ARG GRAFANA_TGZ="grafana-latest.linux-x64-musl.tar.gz" - -# Make sure we have Gnu tar -RUN apk add --no-cache tar - -COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz - -# Change to tar xfzv to make tar print every file it extracts -RUN mkdir /tmp/grafana && tar xzf /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana - -FROM ${BASE_IMAGE} - -ARG GF_UID="472" -ARG GF_GID="0" - -ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ - 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 - -RUN apk add --no-cache ca-certificates bash tzdata musl-utils -RUN apk info -vv | sort - -# Oracle Support for x86_64 only -RUN if [ `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=0 /tmp/grafana "$GF_PATHS_HOME" - -RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup -S -g $GF_GID grafana; \ - fi - -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser -S -u $GF_UID -G "$GF_GID_NAME" grafana && \ - 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 "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/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" - -EXPOSE 3000 - -COPY ./run.sh /run.sh - -USER "$GF_UID" -ENTRYPOINT [ "/run.sh" ] diff --git a/packaging/docker/build-enterprise.sh b/packaging/docker/build-enterprise.sh deleted file mode 100755 index a55696c4cef..00000000000 --- a/packaging/docker/build-enterprise.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -set -e - -UBUNTU_BASE=0 - -while [ "$1" != "" ]; do - case "$1" in - "--ubuntu") - UBUNTU_BASE=1 - 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 - -if [ ${UBUNTU_BASE} = "0" ]; then - TAG_SUFFIX="" - DOCKERFILE="Dockerfile" -else - TAG_SUFFIX="-ubuntu" - DOCKERFILE="ubuntu.Dockerfile" -fi - -echo "Building and deploying ${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" - -docker build \ - --tag "${_docker_repo}:${_grafana_tag}${TAG_SUFFIX}" \ - --no-cache=true \ - -f ${DOCKERFILE} \ - . - -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 - diff --git a/packaging/docker/build.sh b/packaging/docker/build.sh index 533284ac8af..f1fcf443886 100755 --- a/packaging/docker/build.sh +++ b/packaging/docker/build.sh @@ -28,7 +28,7 @@ done _grafana_tag=${1:-} _docker_repo=${2:-grafana/grafana} -# If the tag starts with v, treat this as a official release +# If the tag starts with v, treat this as an official release if echo "$_grafana_tag" | grep -q "^v"; then _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) else @@ -59,23 +59,25 @@ docker_build () { esac if [ $UBUNTU_BASE = "0" ]; then libc="-musl" - dockerfile="Dockerfile" base_image="${base_arch}alpine:3.15" else libc="" - dockerfile="ubuntu.Dockerfile" base_image="${base_arch}ubuntu:20.04" fi - grafana_tgz="grafana-latest.linux-${arch}${libc}.tar.gz" + 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 \ - -f "${dockerfile}" \ + --file ../../Dockerfile \ . } diff --git a/packaging/docker/custom/Dockerfile b/packaging/docker/custom/Dockerfile index 0bfed47c44c..3a4c6aa1bbd 100644 --- a/packaging/docker/custom/Dockerfile +++ b/packaging/docker/custom/Dockerfile @@ -1,51 +1,56 @@ -ARG GRAFANA_VERSION="latest" - -FROM grafana/grafana:${GRAFANA_VERSION} - -USER root - -ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" - -ARG GF_GID="0" -ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" - -RUN mkdir -p "$GF_PATHS_PLUGINS" && \ - chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories && \ - echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \ - apk --no-cache upgrade && \ - apk add --no-cache udev ttf-opensans chromium && \ - rm -rf /tmp/* && \ - rm -rf /usr/share/grafana/tools/phantomjs; \ -fi - -USER grafana - -ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/chromium-browser" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - grafana-cli \ - --pluginsDir "$GF_PATHS_PLUGINS" \ - --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ - plugins install grafana-image-renderer; \ -fi - -ARG GF_INSTALL_PLUGINS="" - -RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ - OLDIFS=$IFS; \ - IFS=','; \ - for plugin in ${GF_INSTALL_PLUGINS}; do \ - IFS=$OLDIFS; \ - if expr match "$plugin" '.*\;.*'; then \ - pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ - pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ - grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ - else \ - grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ - fi \ - done \ -fi +ARG GRAFANA_VERSION="latest" + +FROM grafana/grafana:${GRAFANA_VERSION} + +ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" + +ARG GF_GID="0" + +ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" +ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/chrome" + +USER root + +RUN mkdir -p "$GF_PATHS_PLUGINS" && \ + chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" && \ + if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ + if grep -i -q alpine /etc/issue; then \ + apk add --no-cache udev ttf-opensans chromium && \ + ln -s /usr/bin/chromium-browser "$GF_PLUGIN_RENDERING_CHROME_BIN"; \ + else \ + cd /tmp && \ + curl -sLO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ + DEBIAN_FRONTEND=noninteractive && \ + apt-get update -q && \ + apt-get install -q -y ./google-chrome-stable_current_amd64.deb && \ + rm -rf /var/lib/apt/lists/* && \ + rm ./google-chrome-stable_current_amd64.deb && \ + ln -s /usr/bin/google-chrome "$GF_PLUGIN_RENDERING_CHROME_BIN"; \ + fi \ + fi + +USER grafana + +RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ + grafana-cli \ + --pluginsDir "$GF_PATHS_PLUGINS" \ + --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ + plugins install grafana-image-renderer; \ + fi + +ARG GF_INSTALL_PLUGINS="" + +RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ + OLDIFS=$IFS; \ + IFS=','; \ + for plugin in ${GF_INSTALL_PLUGINS}; do \ + IFS=$OLDIFS; \ + if expr match "$plugin" '.*\;.*'; then \ + pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ + pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ + grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ + else \ + grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ + fi \ + done \ + fi diff --git a/packaging/docker/custom/ubuntu.Dockerfile b/packaging/docker/custom/ubuntu.Dockerfile deleted file mode 100644 index 470ec50e6ab..00000000000 --- a/packaging/docker/custom/ubuntu.Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -ARG GRAFANA_VERSION="latest" - -FROM grafana/grafana:${GRAFANA_VERSION}-ubuntu - -USER root - -# Set DEBIAN_FRONTEND=noninteractive in environment at build-time -ARG DEBIAN_FRONTEND=noninteractive - -ARG GF_INSTALL_IMAGE_RENDERER_PLUGIN="false" - -ARG GF_GID="0" -ENV GF_PATHS_PLUGINS="/var/lib/grafana-plugins" - -RUN mkdir -p "$GF_PATHS_PLUGINS" && \ - chown -R grafana:${GF_GID} "$GF_PATHS_PLUGINS" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y gdebi-core && \ - cd /tmp && \ - curl -LO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \ - gdebi --n google-chrome-stable_current_amd64.deb && \ - apt-get autoremove -y && \ - rm -rf /var/lib/apt/lists/*; \ -fi - -USER grafana - -ENV GF_PLUGIN_RENDERING_CHROME_BIN="/usr/bin/google-chrome" - -RUN if [ $GF_INSTALL_IMAGE_RENDERER_PLUGIN = "true" ]; then \ - grafana-cli \ - --pluginsDir "$GF_PATHS_PLUGINS" \ - --pluginUrl https://github.com/grafana/grafana-image-renderer/releases/latest/download/plugin-linux-x64-glibc-no-chromium.zip \ - plugins install grafana-image-renderer; \ -fi - -ARG GF_INSTALL_PLUGINS="" - -RUN if [ ! -z "${GF_INSTALL_PLUGINS}" ]; then \ - OLDIFS=$IFS; \ - IFS=','; \ - for plugin in ${GF_INSTALL_PLUGINS}; do \ - IFS=$OLDIFS; \ - if expr match "$plugin" '.*\;.*'; then \ - pluginUrl=$(echo "$plugin" | cut -d';' -f 1); \ - pluginInstallFolder=$(echo "$plugin" | cut -d';' -f 2); \ - grafana-cli --pluginUrl ${pluginUrl} --pluginsDir "${GF_PATHS_PLUGINS}" plugins install "${pluginInstallFolder}"; \ - else \ - grafana-cli --pluginsDir "${GF_PATHS_PLUGINS}" plugins install ${plugin}; \ - fi \ - done \ -fi diff --git a/packaging/docker/push_to_docker_hub.sh b/packaging/docker/push_to_docker_hub.sh index 09f483965de..cd5a8fd548c 100755 --- a/packaging/docker/push_to_docker_hub.sh +++ b/packaging/docker/push_to_docker_hub.sh @@ -24,18 +24,18 @@ _docker_repo=${2:-grafana/grafana} # If the tag starts with v, treat this as an official release if echo "$_grafana_tag" | grep -q "^v"; then - _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) + _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) else - _grafana_version=$_grafana_tag + _grafana_version=$_grafana_tag fi -export DOCKER_CLI_EXPERIMENTAL=enabled - echo "pushing ${_docker_repo}:${_grafana_version}${TAG_SUFFIX}" +export DOCKER_CLI_EXPERIMENTAL=enabled + docker_push_all () { - repo=$1 - tag=$2 + repo=$1 + tag=$2 # Push each image individually docker push "${repo}:${tag}${TAG_SUFFIX}" @@ -52,18 +52,18 @@ docker_push_all () { } if echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -vq "beta"; then - echo "pushing ${_docker_repo}:latest${TAG_SUFFIX}" - docker_push_all "${_docker_repo}" "latest" - docker_push_all "${_docker_repo}" "${_grafana_version}" - # Push to the grafana-dev repository with the expected tag - # for running the end to end tests successfully + echo "pushing ${_docker_repo}:latest${TAG_SUFFIX}" + docker_push_all "${_docker_repo}" "latest" + docker_push_all "${_docker_repo}" "${_grafana_version}" + # Push to the grafana-dev repository with the expected tag + # for running the end to end tests successfully docker push "grafana/grafana-dev:${_grafana_tag}${TAG_SUFFIX}" elif echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -q "beta"; then - docker_push_all "${_docker_repo}" "${_grafana_version}" - # Push to the grafana-dev repository with the expected tag - # for running the end to end tests successfully + docker_push_all "${_docker_repo}" "${_grafana_version}" + # Push to the grafana-dev repository with the expected tag + # for running the end to end tests successfully docker push "grafana/grafana-dev:${_grafana_tag}${TAG_SUFFIX}" elif echo "$_grafana_tag" | grep -q "main"; then - docker_push_all "${_docker_repo}" "main" + docker_push_all "${_docker_repo}" "main" docker push "grafana/grafana-dev:${_grafana_version}${TAG_SUFFIX}" fi diff --git a/packaging/docker/ubuntu.Dockerfile b/packaging/docker/ubuntu.Dockerfile deleted file mode 100644 index c4bc984edf6..00000000000 --- a/packaging/docker/ubuntu.Dockerfile +++ /dev/null @@ -1,60 +0,0 @@ -ARG BASE_IMAGE=ubuntu:20.04 -FROM ${BASE_IMAGE} AS grafana-builder - -ARG GRAFANA_TGZ="grafana-latest.linux-x64.tar.gz" - -COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz - -RUN mkdir /tmp/grafana && tar xzf /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana - -FROM ${BASE_IMAGE} - -EXPOSE 3000 - -# Set DEBIAN_FRONTEND=noninteractive in environment at build-time -ARG DEBIAN_FRONTEND=noninteractive -ARG GF_UID="472" -ARG GF_GID="0" - -ENV PATH=/usr/share/grafana/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ - 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 -# We need curl in the image -RUN apt-get update && apt-get install -y ca-certificates curl tzdata && \ - apt-get autoremove -y && rm -rf /var/lib/apt/lists/*; - -COPY --from=grafana-builder /tmp/grafana "$GF_PATHS_HOME" - -RUN if [ ! $(getent group "$GF_GID") ]; then \ - addgroup --system --gid $GF_GID grafana; \ - fi - -RUN export GF_GID_NAME=$(getent group $GF_GID | cut -d':' -f1) && \ - mkdir -p "$GF_PATHS_HOME/.aws" && \ - adduser --system --uid $GF_UID --ingroup "$GF_GID_NAME" grafana && \ - 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 "$GF_PATHS_HOME/conf/sample.ini" "$GF_PATHS_CONFIG" && \ - cp "$GF_PATHS_HOME/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 ./run.sh /run.sh - -USER "$GF_UID" -ENTRYPOINT [ "/run.sh" ] diff --git a/pkg/build/docker/build.go b/pkg/build/docker/build.go index 7267d4a094b..fabc06c1644 100644 --- a/pkg/build/docker/build.go +++ b/pkg/build/docker/build.go @@ -70,12 +70,10 @@ func BuildImage(version string, arch config.Architecture, grafanaDir string, use } libc := "-musl" - dockerfile := "Dockerfile" baseImage := fmt.Sprintf("%salpine:3.15", baseArch) tagSuffix := "" if useUbuntu { libc = "" - dockerfile = "ubuntu.Dockerfile" baseImage = fmt.Sprintf("%subuntu:20.04", baseArch) tagSuffix = "-ubuntu" } @@ -118,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", - "-f", dockerfile, ".", + "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) } @@ -154,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) }