Golang container image - это реализация легковесной сборки ЯП Golang на базе Astra Linux
Присоединяйтесь к нашим социальным сетям:
- Docker >= 28.1.1 (возможно работает в предыдущих версиях, но мы не можем это гарантировать)
OS | Golang | Status |
---|---|---|
✅ Fully supported | ||
✅ Fully supported |
Go(a.k.a Golang) - язык программирования, впервые разработанный в Google. Это статически типизированный язык с синтаксисом, в некоторой степени производным от C, но с дополнительными функциями, такими как сборщик мусора, безопасность типов, некоторые возможности динамической типизации, дополнительные встроенные типы (например, массивы переменной длины и карты ключ-значение) и большая стандартная библиотека. Образ построен на основе отечественной ОС Astra Linux
Для начала работы необходимо установить pre-commit и хуки
$ pip install pre-commit
$ pre-commit --version
pre-commit 4.2.0
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
pre-commit installed at .git/hooks/commit-msg
pre-commit installed at .git/hooks/pre-push
Warning
Чтобы проверить свои изменения, воспользуйтесь командой pre-commit run --all-files
.
Чтобы проверить конкретную задачу, воспользуетесь командой pre-commit run <target> --all-files
.
Если Вы понимаете что творите и хотите пропустить проверку pre-commit
-ом воспользуйтесь --no-verify
, пример git commit -m "Добавил изменения и не хочу проверки" --no-verify
Существует несколько способов как можно взаимодействовать со сборкой образа. Благодаря скрипту1 может существовать 3 способа передачи аргумента в Dockerfile
:
-
Передача 'примерной' версии. В результате передачи данной строки, скрипт попытается найти точную версии, если таковой нет, то будет возвращена пустая строка
## Export Golang version for 1.7.5 $ export GOLANG_VERSION='1.19-astra1.7.5-slim' ## Golang image: 512MB docker build \ --progress=plain \ --build-arg go_identity=1.19 \ --build-arg image_version=1.7.5-slim \ -t golang:"${GOLANG_VERSION}" \ . .. build ...
-
Передача точной версии
## Export Golang version for 1.8.2 $ export GOLANG_VERSION='1.21-astra1.8.2-slim' ## Golang build utils image: 632MB docker build \ --progress=plain \ --build-arg go_identity='2:1.21~2.astra1+b1' \ --build-arg image_version=1.8.2-slim \ -t golang:"${GOLANG_VERSION}" \ . .. build ...
-
Передача ссылки, на заранее собранный из исходников Golang
## Export Golang version for 1.8.2 $ export GOLANG_VERSION='1.23-astra1.8.2-slim' ## Golang build utils image: 645MB docker build \ --progress=plain \ --build-arg go_identity=https://example-registry.com/repository/golang/go-v1.23.5-linux-amd64.tar.gz \ --build-arg image_version=1.8.2-slim \ -t golang:"${GOLANG_VERSION}" \ . .. build ...
Tip
Примеры просмотра версии пакета -
apt show golang
,
apt-cache policy golang
,
apt-cache show golang
Имя | Значение по умолчанию | Тип | Описание |
---|---|---|---|
image_name |
astra | string | Имя образа. |
image_registry |
'' | string | Адрес до реестра образа2. |
image_version |
1.8.2-slim | string | Версия образа. |
go_registry_proxy |
'' | string | Переменная, для установки своего проксирующего репозитория. |
go_identity |
1.21 | string | Ожидаемая версия Golang1. |
В результате сборки базового образа идёт наполнение файла /etc/environment
. В нём отражены общие переменные, которые могут использоваться в сборочных образах приложений
-
Пример переменных для образа
1.23
установленного из удаленного и скомпилированного Golang$ cat /etc/environment GO_REVISION=Installed-from-URL BEGIN_BUILD_IN_EPOCH=1746645898 GO_MAJOR_MINOR_PATCH_VERSION=1.23.4 GO_MAJOR_MINOR_VERSION=1.23
-
Пример переменных для образа
1.21
из репозиториев Astra Linux$ cat /etc/environment GO_REVISION=2:1.21~2.astra1+b1 BEGIN_BUILD_IN_EPOCH=1746643737 GO_MAJOR_MINOR_PATCH_VERSION=1.21.10 GO_MAJOR_MINOR_VERSION=1.21
-
Пример переменных для образа
1.19
из репозиториев Astra Linux$ cat /etc/environment GO_REVISION=2:1.19~1 BEGIN_BUILD_IN_EPOCH=1746643927 GO_MAJOR_MINOR_PATCH_VERSION=1.19.12 GO_MAJOR_MINOR_VERSION=1.19
Для того чтобы начать использовать данный образ, создайте Dockerfile
с простыми настройками
FROM golang:1.21-astra1.8.2-slim
WORKDIR /usr/src/app
# pre-copy/cache go.mod for pre-downloading dependencies and only redownloading them in subsequent builds if they change
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -v -o /usr/local/bin/app ./...
CMD ["app"]
Затем соберите и запустите полученный образ
$ docker build -t my-golang-app .
$ docker run -it --rm --name my-running-app my-golang-app
...run logic...
Для того, чтобы запустить компиляцию внутри докер контейнера
$ docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.21-astra1.8.2-slim go build -v
...run logic...
Кросс-компиляция приложения внутри контейнера
$ docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp -e GOOS=windows -e GOARCH=386 golang:1.21-astra1.8.2-slim go build -v
...run logic...
Альтернативный подход для сборки всех платформ за один раз
$ docker run --rm -it -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.21-astra1.8.2-slim bash
$ for GOOS in darwin linux; do
> for GOARCH in 386 amd64; do
> export GOOS GOARCH
> go build -v -o myapp-$GOOS-$GOARCH
> done
> done
...run logic...
Простой тест:
docker run --rm golang:1.21-astra1.8.2 bash -c "go install github.com/cosmos72/gomacro@latest && gomacro -e 'import \"fmt\"' -e 'fmt.Println(\"Hello from Go\")'"
Данный раздел будет обеспечивать краткие вводные для того, чтобы Вы в дальнейшем могла проектировать свои Scratch
сборки, на примере небольшой утилиты. Все, что демонстрируется, также подкреплено и всеми задействованными скриптами сборочными или специализированными для сборки через scratch
. Все манипуляции поделены на определенное количество 'шагов' для которых будут даны краткие комментарии:
-
Первый этап - установка базовых компонентов для сборки
## Install upx and base components RUN \ --mount=type=bind,source=./scripts,target=/usr/local/sbin,readonly \ upx-install.sh \ && apt-install.sh \ tzdata \ zip \ ca-certificates \ build-essential \ && apt-remove.sh
-
Второй этап - упаковка минимального набора компонентов для переноса в
Scratch
## Create anonymous user RUN \ mkdir -p \ /base/etc/ssl/certs \ /base/sbin \ /base/usr/src/app \ ## UID and GID && echo 'root:x:0:' > /base/etc/group \ && echo "${user}:x:${gid}:" >> /base/etc/group \ && echo 'root:x:0:0:root:/root:/sbin/nologin' > /base/etc/passwd \ && echo "${user}:x:${uid}:${gid}:${user}:/nonexistent:/sbin/nologin" >> /base/etc/passwd \ ## Nologin binary && echo 'int main() { return 1; }' > nologin.c \ && gcc -Os -no-pie -static -std=gnu99 -s -Wall -Werror -o /base/sbin/nologin nologin.c \ ## Copy root cert && cp /etc/ssl/certs/ca-certificates.crt /base/etc/ssl/certs/ca-certificates.crt WORKDIR /usr/share/zoneinfo RUN zip -q -r -0 /base/zoneinfo.zip .
-
Третий этап - сборка и оптимизация приложения при помощи
upx
WORKDIR /opt COPY scratch/go.* . RUN go mod download COPY scratch/main.go . RUN \ go build \ -v \ -ldflags "-extldflags '-static' -w -s -X 'main.AppVersion=${version}'" \ -installsuffix=static \ -o curl-uri main.go ## Reduce binary size: ~5.7Mb => ~1,8Mb RUN \ echo "Original binary size: $(du -hs curl-uri)" \ && upx --best --lzma -o curl_uri_compressed curl-uri \ && echo "Compressed binary size: $(du -hs curl_uri_compressed)" ## Copy optimized app RUN \ cp curl_uri_compressed /base/usr/src/app/curl-uri \ && chmod 755 /base/usr/src/app/curl-uri
-
Заключительный этап - миграция к скретч и запуск приложения
## Import the user and group files from the base-stage COPY --from=base-stage /base/ / ## Use an unprivileged user USER anonymous:anonymous ## Set timezone data environment ENV \ ZONEINFO=/zoneinfo.zip \ PATH="/usr/src/app" \ SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \ REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt ## Run dir WORKDIR /usr/src/app ## Be gentle and expose port EXPOSE 8080 ENTRYPOINT [ "curl-uri" ]
Сборка: docker build --progress=plain -f Dockerfile-scratch -t curl-uri:1.0.0 .
Запуск: docker run --rm --network=host --dns 8.8.8.8 -e IPINFO_TOKEN=4426e4d4334a8d curl-uri:1.0.0
Warning
Если IPINFO_TOKEN
не определяется, то зарегистрируйте новый на ipinfo.io
Примеры использования:
-
Route
/
- вывод версии приложения$ curl http://localhost:8080 Golang UPX Demo v1.0.0
-
Route
/location
- запрос информации о своём местонахождении$ curl http://localhost:8080/location ____ __ Welcome to the bloated Golang server! /\ _'\ /\ \ \ \ \L\_\ ___ _____\ \ \___ __ _ __ ____ [+] Server IP: 8.8.8.8 \ \ \L_L / __'\/\ '__'\ \ _ '\ /'__'/\''__/',__\ [+] Country: ZN \ \ \/, /\ \L\ \ \ \L\ \ \ \ \ \/\ __\ \ \/\__, '\ [+] Region: Amsterdam \ \____\ \____/\ \ ,__/\ \_\ \_\ \____\ \_\/\____/ [+] City: Amsterdam \/___/ \/___/ \ \ \/ \/_/\/_/\/____/\/_/\/___/ [+] ISP: Google cloud \ \_\ [+] Lat/Lon: 11.1111, 11.1111 \/_/ [+] Timezone: Europe/Amsterdam Server started at: Wed May 7 23:27:27 MSK 2025 Current time: Wed May 7 23:27:33 MSK 2025
-
Route
/stream
- последовательно выводит framerate изAscii
артов$ curl http://localhost:8080/stream ____ __ /\ _'\ /\ \ \ \ \L\_\ ___ _____\ \ \___ __ _ __ ____ \ \ \L_L / __'\/\ '__'\ \ _ '\ /'__'/\''__/',__\ \ \ \/, /\ \L\ \ \ \L\ \ \ \ \ \/\ __\ \ \/\__, '\ \ \____\ \____/\ \ ,__/\ \_\ \_\ \____\ \_\/\____/ \/___/ \/___/ \ \ \/ \/_/\/_/\/____/\/_/\/___/ \ \_\ \/_/ Uptime: 1s
-
Route
/live
- выводитtext/plain
(по умолчанию) проверку работоспособности сервера и функционала. Также поддерживает работу с query$ curl http://localhost:8080/live OK $ curl http://localhost:8080/live failed to fetch public IP $ curl http://localhost:8080/live?format=json {"error":"failed to fetch public IP","status":"error"}
-
Route
/healthz
- выводитtext/plain
(по умолчанию) проверку сервера на его способность принимать запросы. Также поддерживает работу с query$ curl http://localhost:8080/healthz OK $ curl http://localhost:8080/healthz?format=json {"status":"ok"}
-
Route
/metrics
- выводитtext/plain
Prometheus метрики$ curl http://localhost:8080/metrics ... # HELP upx_server_requests_total Total number of HTTP requests. # TYPE upx_server_requests_total counter upx_server_requests_total{handler="location",method="GET"} 1 # HELP upx_server_up Whether the server is up and responding (1 = yes, 0 = no) # TYPE upx_server_up gauge upx_server_up 1
Полный Dockerfile
:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Base image #
# First stage, prepare environment #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
FROM golang:1.21-astra1.8.2-slim AS base-stage
SHELL [ "/bin/bash", "-exo", "pipefail", "-c" ]
ARG \
user=anonymous \
uid=100000 \
gid=65536 \
version=1.0.0
## Disable CGO by default and try to avoid installing the package: `libc6-compat`
# Source: https://stackoverflow.com/questions/62634820/build-small-image-from-scratch-open-no-such-file-or-directory
# Source: https://www.reddit.com/r/golang/comments/pi97sp/what_is_the_consequence_of_using_cgo_enabled0/
ENV CGO_ENABLED=0
## Install upx and base components
RUN \
--mount=type=bind,source=./scripts,target=/usr/local/sbin,readonly \
upx-install.sh \
&& apt-install.sh \
tzdata \
zip \
ca-certificates \
build-essential \
&& apt-remove.sh
## Create anonymous user
# hadolint ignore=SC2154
RUN \
mkdir -p \
/base/etc/ssl/certs \
/base/sbin \
/base/usr/src/app \
## UID and GID
&& echo 'root:x:0:' > /base/etc/group \
&& echo "${user}:x:${gid}:" >> /base/etc/group \
&& echo 'root:x:0:0:root:/root:/sbin/nologin' > /base/etc/passwd \
&& echo "${user}:x:${uid}:${gid}:${user}:/nonexistent:/sbin/nologin" >> /base/etc/passwd \
## Nologin binary
&& echo 'int main() { return 1; }' > nologin.c \
&& gcc -Os -no-pie -static -std=gnu99 -s -Wall -Werror -o /base/sbin/nologin nologin.c \
## Copy root cert
&& cp /etc/ssl/certs/ca-certificates.crt /base/etc/ssl/certs/ca-certificates.crt
WORKDIR /usr/share/zoneinfo
## -0 means no compression. Needed because go's
## tz loader doesn't handle compressed data
RUN zip -q -r -0 /base/zoneinfo.zip .
WORKDIR /opt
## Top-level layer for pumping dependencies
## Necessary, because subsequently the changeable
## layers, which are located below, will change
## and this layer will not be recreated, thereby
## optimizing the build time
COPY scratch/go.* .
RUN go mod download
## The level below, which assumes frequent changes.
## In order to optimize the build time, it is necessary
## to place it below, because the subsequent build
## will analyze the hash checksums, and based on them
## skip the main "long" build, going straight to the
## final part, where the code base will change
## regularly, thereby rebuilding only this layer
## Copy app
COPY scratch/main.go .
## Build app
# hadolint ignore=SC2154
RUN \
go build \
-v \
-ldflags "-extldflags '-static' -w -s -X 'main.AppVersion=${version}'" \
-installsuffix=static \
-o curl-uri main.go
## Reduce binary size: ~9.0Mb => ~2.7Mb
RUN \
echo "Original binary size: $(du -hs curl-uri)" \
&& upx --best --lzma -o curl_uri_compressed curl-uri \
&& echo "Compressed binary size: $(du -hs curl_uri_compressed)"
## Copy optimized app
RUN \
cp curl_uri_compressed /base/usr/src/app/curl-uri \
&& chmod 755 /base/usr/src/app/curl-uri
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Final image #
# Third stage, add only minimal application and deps #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
FROM scratch
## Set base label
LABEL \
maintainer="Vladislav Avdeev" \
organization="NGRSoftlab"
## Import the user and group files from the base-stage
COPY --from=base-stage /base/ /
## Use an unprivileged user
USER anonymous:anonymous
## Set timezone data environment
ENV \
ZONEINFO=/zoneinfo.zip \
PATH="/usr/src/app" \
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
## Run dir
WORKDIR /usr/src/app
## Be gentle and expose port
EXPOSE 8080
ENTRYPOINT [ "curl-uri" ]
Чтобы переопределить/переназначить проектную область на свои источники в зависимостях, можно воспользоваться следующей инструкцией:
- Создать форк необходимого проекта
- Изменить
go.mod
источник на имя нового форка, зафиксировать и отправить изменения - Добавить в
go.mod
директиву replace. Пример содержимого:
module <yourname>
go 1.18
require (
github.com/versent/saml2aws/v2 v2.35.0
)
replace github.com/versent/saml2aws/v2 v2.35.0 => github.com/marcottedan/saml2aws/v2 master
Более подробно можно ознакомиться тут
Команда go поддерживает базовую аутентификацию HTTP при обмене данными с прокси-серверами
Учетные данные могут быть указаны в файле .netrc
. Например, файл .netrc
, содержащий следующие строки, будет настраивать команду go для подключения к машине proxy.corp.example.com
с заданными именем пользователя и паролем
machine proxy.corp.example.com
login user
password password
Местоположение файла может быть установлено с помощью переменной среды NETRC
. Если NETRC
не установлен, команда go
будет читать $HOME/.netrc
на UNIX-подобных платформах или %USERPROFILE%\_netrc
в Windows
Поля в .netrc
разделяются пробелами, табуляциями и символами новой строки. К сожалению, эти символы нельзя использовать в именах пользователей или паролях. Также обратите внимание, что имя компьютера не может быть полным URL-адресом, поэтому невозможно указать разные имена пользователей и пароли для разных путей на одном компьютере
В качестве альтернативы учетные данные могут быть указаны непосредственно в URL-адресах GOPROXY
. Например:
GOPROXY=https://user:password@proxy.corp.example.com
Альтернативная опция при помощи git
-a при CI/CD
# От пользователя
git config --global credential.helper store
git credential fill <<! | git credential approve
url=https://proxy.corp.example.com
username=user
password=password
!
Warning
Соблюдайте осторожность при использовании этого подхода: переменные среды могут отображаться в истории оболочки и в журналах
Лого для проекта создано при помощи aasvg
проекта. Вы можете создать такое же и/или модифицировать имеющееся. Для этого воспользуйтесь сайтом или установите figlet
. Если Вы используете способ с установкой figlet
, то вдобавок необходимо сказать необходимый шрифт, например я использую Doom
. Далее, необходимо воспользоваться aasvg
и конвертировать ascii
арт в svg
. Обратите внимание - по умолчанию будет svg в красном цвете, чтобы изменить цвет, необходимо изменить его определение тут
$ curl 'http://www.figlet.org/fonts/doom.flf' -o /usr/share/figlet/doom.flf
$ curl 'http://www.figlet.org/fonts/larry3d.flf' -o /usr/share/figlet/larry3d.flf
$ figlet -f doom 'Golang'
_____ _
| __ \ | |
| | \/ ___ | | __ _ _ __ __ _
| | __ / _ \| |/ _` | '_ \ / _` |
| |_\ | (_) | | (_| | | | | (_| |
\____/\___/|_|\__,_|_| |_|\__, |
__/ |
|___/
$ aasvg --source --embed < docs/ascii.txt > docs/images/logo.svg
![]() Gopher mascot.
|
Footnotes
-
🛠️ За счёт скрипта
go-install-approximately.sh
нас может не волновать полная версия Golang, мы можем передавать лишь приблизительно желаемую версию, а скрипт позаботится чтобы была выбрана последняя и актуальная из списка ↩ ↩2 -
🛠️ Например можно использовать свой приватный реестр образов:
--build-arg image_registry=my-container-registry:1111/
↩