Обновлено 11 июля 2020 г.
Так называемый «минимальный» образ кота является относительным, и его размер зависит от следующего:
- Использует ли базовый образ glibc, то есть использовать ли alpine в качестве базового образа;
- Используйте jdk или просто используйте jre в качестве среды выполнения tomcat;
- Используйте openjdk или oracle jdk.
Вышеуказанные условия определяют размер изображения кота.
Как мы все знаем, alpine — самый маленький из базовых образов, он тоже идет с менеджером пакетов, но его недостатки тоже очевидны, то есть он не использует glibc, поэтому принесет проблемы с совместимостью.
В этой статье в качестве базового образа будет использоваться дистрибутив на основе glibc (на основе debian), а затем будет использоваться oracle jdk8 + tomcat8, окончательный размер образа 181M (можно меньше, но это будет непрактично). Этот размер имеет определенное плавающее пространство, потому что даже если используется oracle jdk8, размер разных младших версий будет сильно различаться.
Далее сравнение с официальным зеркалом:
имя зеркала | java | размер | зеркальный слой | glibc |
---|---|---|---|---|
tomcat:8 | openjdk jre | 463MB | 31 | glibc |
tomcat:8-alpine | openjdk jre | 106MB | 25 | muslc |
tomcat:8-slim | openjdk jre | 223MB | 29 | glibc |
В этой статье собраны и использованы | oracle jdk | 175M | 3 | glibc |
Видно, что преимущество alpine очень большое, оно достаточно маленькое, но использует jre, а не glibc. Если ваша программа скомпилирована с использованием glibc, при ее запуске возникнут проблемы. Я не уверен, что развитие моей компании сильно зависит от glibc, но я не рискну, и у alpine для меня нет никаких преимуществ.
Вы можете видеть, что слой изображения tomcat, скомпилированный и используемый в этой статье, состоит всего из 3 слоев.Вы можете быть удивлены количеством слоев.Вы поймете, когда прочитаете это, потому что этот образ не построен через dockerfile.
Поскольку я загрузил скомпилированный образ в dockerhub, вы можете использовать его напрямую.docker run maxadd/tomcat:8-jdk8-distroless
запустить представление или использоватьdiveОзнакомьтесь с его составом.
причина
Когда вы выбираете изображение кота, на самом деле нужно учитывать множество вещей:
- есть ли необходимый заказ;
- Может ли Java удовлетворить потребности;
- Является ли он достаточно гибким для настройки;
- Достаточно ли безопасно (достаточно мало команд и библиотечных файлов);
- Достаточно ли он мал.
Действительно, когда вам нужно его использовать, вы обнаружите, что официальное зеркало более или менее неудобно в использовании, и это не так уж удовлетворительно. Для меня самое главное, что нет официального зеркала оракула jdk, потому что оракул собачьих дней должен брать плату за оракул jdk. Хотя некоторые люди предоставили свою собственную версию, основанную на oracle jdk, зеркало слишком велико.
Так или иначе, по той или иной причине я собирался вручную создать собственный образ кота, что заставило меня обратить внимание наdistrolessзеркало. Поскольку образ без дистрибутива является самым маленьким среди всех образов на основе glibc, всего 19 МБ, он содержит только самую базовую рабочую среду, которую должна иметь двоичная программа, и не предоставляет никаких команд, включая оболочку.
Поскольку дистрибутив заблокирован, я загрузил его на dockerhub под именем
maxadd/distroless_base-debian10
. Такое зеркало в принципе невозможно сделать руками и ногами, вы можете использовать его напрямую.
Поскольку я не знал, что команда ADD в dockerfile может напрямую распаковывать tar-пакет, я также специально изучил инструмент bazel для сборки distroless, поэтому в этой статье будет упомянута реализация на основе bazel. Неважно, если вы не знаете базель, просто используйте ДОБАВИТЬ.
Существуют некоторые различия между использованием bazel для создания образа и созданием образа на основе dockerfile.При использовании bazel создается только один слой образа, независимо от того, сколько операций вы выполняете; при использовании dockerfile каждый раз, когда вы выполняете команду dockerfile, будет генерироваться слой изображения, в том числеENV
такие команды. И вdiveС точки зрения команды образы, созданные ими, также будут разными.
На самом деле, основная причина в том, что эти два понятия различны: Bazel напрямую создает образ за один раз и предоставляет все файлы, необходимые для запуска контейнера, в то время как dockerfile использует концепцию слоя образа, и каждый раз инструкция выполняется, к ней добавляется слой. Если изучать bazel для этой разницы нерентабельно, рекомендуется использовать dokefile напрямую. Однако оба метода будут упомянуты ниже.
С этой предпосылкой я начал планировать свое зеркало:
- Чтобы установить jdk, потому что вам нужно использовать некоторые команды в jdk;
- Предоставляет более 300 основных команд через busybox;
- Установите часовой пояс зеркала на Азию/Шанхай;
- Пусть зеркало поддерживает китайский;
- Напишите скрипт для самостоятельного запуска tomcat, в скрипте catalina.sh задействовано слишком много команд, нет необходимости его использовать;
- Используйте jmx_prometheus_javaagent для мониторинга jvm tomcat;
-
Чтобы установить bash, используйте его для установки параметров jvm(Необязательно);
Следующие шаги для достижения вышеуказанных требований.
установить Баш
Мой подход заключается в создании каталога в качестве корневого каталога, в котором хранятся все файлы, которые необходимо скопировать в образ без дистрибутива. В том месте, где необходимо разместить файл, создайте соответствующий каталог в этом каталоге. Наконец, упакуйте этот «корневой каталог» и разархивируйте его в корневой каталог дистрибутива, и вы сможете получить все файлы за один шаг. Это также является причиной того, что зеркальный слой имеет только 3 слоя, 2 из которых предоставляются distroless.
Первый шаг — установить bash.Цель установки bash — выполнение сценариев, а также возможность входа в систему для выполнения таких команд, как jmap и jstack. Поскольку мы будем использовать busybox позже,busybox предоставит ш, так что вам решать, устанавливать bash или нет. На примере изображения этого нет.
Как упоминалось ранее, я использую distroless в качестве базового образа здесь, и поскольку distroless использует файлы библиотеки debian, мы можем напрямую скопировать команды в debian для использования.
Для работы команд в Linux требуется не только сама команда, но и файлы библиотек, от которых она зависит.ldd
команда для просмотра. Так что нам нужно скопировать не только саму команду, но и нужные ей файлы библиотеки.
Поскольку эта версия образа без дистрибутиваgcr.io/distroless/base-debian10
, поэтому сначала нам нужно запустить контейнер Debian. Хотя имя образа показывает, что он использует debian10, я обнаружил, что есть проблема с портированием bash от debian10 на distroless, но с использованием debian9 проблем нет, поэтому здесь я буду использовать bash от debian9.
# docker run -it --name debian debian:9 /bin/bash
Просмотрите файлы библиотек, от которых зависит bash:
root@45104fade344:/# ldd /bin/bash
linux-vdso.so.1 (0x00007ffda05b1000) # 这一行无需理会
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fdf4532f000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdf4512b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdf44d8c000)
/lib64/ld-linux-x86-64.so.2 (0x0000564175f7f000)
Всего выше четыре библиотечных файла, но все, что нужно, это/lib/x86_64-linux-gnu/libtinfo.so.5
, другие файлы библиотеки уже существуют в дистрибутиве.
Сначала мы создаем так называемый «корневой каталог» на хосте, который здесь называется tomcat_jdk8. Затем создайте в этом каталогеlib/x86_64-linux-gnu
,bin
,etc
,usr/local
,usr/lib/locale
эти каталоги.
mkdir -p tomcat_jdk8/{lib/x86_64-linux-gnu,bin,etc,usr/{lib/locale,local}}
Затем используйте команду docker cp, чтобы скопировать команды и файлы библиотеки из контейнера debian в соответствующий каталог, который мы создали.
docker cp debian:/bin/bash tomcat_jdk8/bin/
# -L 表示复制链接文件指向的实际文件
docker cp -L debian:/lib/x86_64-linux-gnu/libtinfo.so.5 tomcat_jdk8/lib/x86_64-linux-gnu/
Таким образом, вы можете скопировать все остальные команды, которые хотите использовать, и я не буду демонстрировать их здесь одну за другой.
подготовить JDK
Потому что здесь я собираюсь использовать oracle jdk вместо openjdk, поэтому начнем софициальный сайт оракулаЗагрузите jdk8 выше. Я скачал здесь версию 162, ни по какой другой причине, просто потому, что компания использует эту версию.
Обратите внимание на то, чтобы скачать пакет tar и разархивировать его.Здесь я разархивирую java в каталог /usr/local:
# ls tomcat_jdk8/usr/local
jdk1.8.0_162
Полный jdk имеет в общей сложности 371M, и в нем есть много вещей, которые мы не используем, поэтому сначала удалите их:
# cd tomcat_jdk8/usr/local/jdk1.8.0_162
# rm -rf *src.zip \
lib/missioncontrol \
lib/visualvm \
lib/*javafx* \
jre/lib/plugin.jar \
jre/lib/ext/jfxrt.jar \
jre/bin/javaws \
jre/lib/javaws.jar \
jre/lib/desktop \
jre/plugin \
jre/lib/deploy* \
jre/lib/*javafx* \
jre/lib/*jfx* \
jre/lib/amd64/libdecora_sse.so \
jre/lib/amd64/libprism_*.so \
jre/lib/amd64/libfxplugins.so \
jre/lib/amd64/libglass.so \
jre/lib/amd64/libgstreamer-lite.so \
jre/lib/amd64/libjavafx*.so \
jre/lib/amd64/libjfx*.so
После удаления осталось всего 153M. Затем создайте мягкую ссылку на каталог jdk:
# ln -s jdk1.8.0_162 java
jdk-зависимости
В каталоге bin jdk есть много команд, которые нам нужны, и эти команды также имеют зависимые библиотечные файлы. Хотя jdk загружается нами, а не устанавливается нами, поскольку команды в jdk представляют собой скомпилированные двоичные файлы, их можно запускать до тех пор, пока выполняются требования ядра и glibc.
Конечно, ядро и glibc — это просто жесткие требования, а мягкие требования — это библиотеки, от которых они зависят. Поскольку мой хост Linux — это CentOS7, а не Debian, нам нужно смонтировать jdk в образ debian и использовать команду ldd в образе, чтобы увидеть, от каких библиотечных файлов зависят команды в jdk.
Я проверил их все и обнаружил, что файлы библиотек в дистрибутивном образе могут полностью удовлетворить текущие потребности всех команд jdk, поэтому никаких дополнительных файлов не требуется. Конечно, в более новой версии jdk могут быть и другие зависимости.Вы можете использовать команду погружения, чтобы проверить, какие файлы библиотек существуют в образе без дистрибутива, а затем сравнить файлы библиотек, от которых зависит команда.Если они не существуют в distroless, то вы должны предоставить его.
Хорошо, следующим шагом будет подготовка кота.
подготовить кота
В tomcat нет команд, и он также запускается java, поэтому он не имеет никаких зависимостей от библиотечных файлов. Просто перейдите к следующему на официальном сайте, что я использую здесьapache-tomcat-8.5.56
.
Я также поместил его в каталог usr/local здесь:
# ls tomcat_jdk8/usr/local/
apache-tomcat-8.5.56 java jdk1.8.0_162
Запускаем tomcat через catalina.sh, но т.к. в нем слишком много команд, и нам нужно только запустить tomcat, не нужно останавливать или перезапускать, поэтому мы можем полностью использовать catalina.sh, просто нужно, чтобы он стартовал с требуемой java параметры. После получения этих параметров мы также можем запустить его непосредственно после передачи непосредственно в java.
Этот параметр на самом деле очень легко получить, вы одновременно сопоставляете tomcat и jdk с контейнером debian, а затем определяетеJAVA_HOME
, вы можете пройтиsh -x catalina.sh run
Смотрите параметры, которые он наконец запускает. Даже я подозреваю, что пока он выполняется прямо на линукс-сервере, в дебиане его монтировать не нужно.
Я не буду демонстрировать здесь конкретную операцию, просто вставлю ее параметры напрямую. Если у вас не установлены параметры JAVA, его параметры запуска следующие:
/usr/local/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
Если вы хотите увеличить параметр jvm, просто вставьте его, вы определяете в catalina.sh аналогичноJAVA_OPS
и т. д., в конечном итоге будут преобразованы в параметры Java. Однако, похоже, что параметры кучи в jvm должны быть добавлены до-server
.
-server -Xmx128M -Xms128M
Мы хотим контролировать размер кучи tomcat jvm через переменную среды, поэтому нам нужно запустить tomcat через скрипт:
#!/bin/sh
/usr/local/java/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server ${JAVA_OPTS} -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp -Djdk.tls.ephemeralDHKeySize=2048 org.apache.catalina.startup.Bootstrap start
Не только размер кучи, любые параметры, которые вам нужны, могут быть определены вJAVA_OPTS
возможный результат состоит в том, что эта переменная будет очень длинной. Вы можете разместить этот скрипт где угодно, пока CMD указывает на его выполнение, он находится здесь/usr/local/
каталоге, имя сценария — start.sh.
Затем установите мягкое соединение с tomcat, и, наконец, содержимое usr/local:
ls tomcat_jdk8/usr/local/
apache-tomcat-8.5.56 config.yml java jdk1.8.0_162 tomcat
jmx монитор кота
Основным средством мониторинга tomcat по-прежнему является jmx, и как tomcat, так и java поддерживают jmx. Здесь проходит мониторинг jmxjmx_exporterDo, это используется с prometheus. Это агент Java, через-javaagent
Параметр запуска, я не буду здесь больше упоминать о java-агенте, потому что я мало что знаю.
После завершения загрузки. я вставил этоusr/local/
каталог, затем дайте ему файл с именемconfig.yml
файл конфигурации:
---
startDelaySeconds: 0
ssl: false
lowercaseOutputName: false
lowercaseOutputLabelNames: false
whitelistObjectNames:
- "com.alibaba.druid:type=DruidDataSource,*"
- "java.lang:*"
Здесь задается белый список для объектов, собираемых jmx, которые собираются только в том случае, если имена объектов совпадают. Если вы не знаете, какие объекты предоставляет tomcat, вы можете использовать jconsole для подключения к jmx и проверки содержимого под тегом mbean, в нем будут перечислены все объекты, предоставляемые в настоящее время jmx.
Поскольку наша разработка использует пул соединений druid от alibaba, его показатели также собираются здесь. Конечно, если вы хотите собрать метрики всего jmx, просто удалите вайтлист. Но я не рекомендую вам это делать, потому что индикаторов слишком много. На примере изображения толькоjava.lang:*
, и не собирает содержимое пула соединений друида. Это просто пример того, что нужно делать, если вы хотите собирать другие показатели.
Запуск tomcat не загружает этот java-agnet по умолчанию, вам нужно добавить его вJAVA_OPTS
в этой переменной окружения. Способ запуска следующий:
-javaagent:/usr/local/jmx_prometheus_javaagent-0.13.0.jar=12356:/usr/local/config.yml
О том, как запустить через докер, будет сказано позже. После запуска зеркала, как это, вам нужно только получить доступhttp://IP:12356/metrics
(ip-адрес контейнера), он распечатает все собранные метрики jmx.
использовать занятой ящик
busybox — это команда Linux, которая может имитировать более 300 распространенных команд Linux размером менее 1 М. Конкретный принцип реализации еще не ясен, но он очень подходит для сценариев, требующих места для хранения.
Мы можем установить busybox в контейнер debian10, а затем скопировать его в каталог tomcat_jdk/bin с помощью команды docker cp (файл зависимой библиотеки distroless уже существует).
Его использование очень простое, например, если вы хотите смоделировать через него команду ls, вы можете сделать это:
./busybox ls /etc/
Второй способ его использования — создать файл программной ссылки ls, указывающий на busybox:
ln -s busybox ls
./ls /etc/
Это всего лишь пример команды ls, другие команды используются таким же образом. Итак, какие команды он поддерживает для моделирования? пройти черезbusybox --list
можно посмотреть. Вы можете создать символические ссылки для всех поддерживаемых команд следующими способами:
# docker run --rm -it -v tomcat_jdk8/bin:/opt debian:10 /bin/bash
root@e39f29c2648d:/# cd /opt/
root@e39f29c2648d:/opt# for i in $(./busybox --list);do ln -s busybox $i;done
Это эквивалентно наличию более 300 команд в вашем образе tomcat.
Китайская поддержка
distroless не поддерживает китайский язык по умолчанию, и сделать так, чтобы он поддерживал китайский язык, очень просто, просто выполните следующую команду в контейнере debain10:
# docker run --rm -it debian:10 /bin/bash
apt update
apt install -y locales
localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
После выполнения команды будет сгенерировано/usr/lib/locale/locale-archive
файл, вам нужно только использовать команду docker cp, чтобы скопировать файл и поместить его в tomcat_jdk8/usr/lib/locale/locale-archive.
Часовой пояс
По умолчанию используется часовой пояс UTC, нам просто нужно поместить файл /usr/share/zoneinfo/Asia/Shanghai в контейнере debian10 в tomcat_jdk8/etc/localtime.
Добавить обычного пользователя
По сути, сам контейнер docker — это процесс в Linux, после того как вы его запустите, вы увидите его на хосте через команду ps, и вы увидите, что запущенный пользователь процесса — root.
Любой, у кого есть здравый смысл в эксплуатации и обслуживании, должен знать, что без крайней необходимости процессы не следует запускать с правами root. Итак, должны ли мы создать обычного пользователя в контейнере, а затем использовать этого обычного пользователя для запуска контейнера? Ответ - не надо.
Поскольку контейнер на самом деле является процессом на хосте, мы можем указать пользователя, которого он запускает, как пользователя на хосте. Когда докер запускает контейнер, вы можете передатьdocker run -u
Укажите имя пользователя хоста, и в k8s вы можете передатьpod.spec.containers.securityContext.runAsUser
чтобы указать uid хоста. Таким образом, вы можете использовать команду ps на узле, на котором запущен контейнер, чтобы увидеть пользователя, указанного пользователем, от имени которого работает контейнер, независимо от того, существует ли пользователь в образе или нет.
Итак, нам не нужно создавать обычного пользователя на хосте.
Если вы решили использовать обычного пользователя для запуска контейнера tomcat, вам лучше изменить владельца некоторых каталогов tomcat (например, каталога журналов tomcat_jdk8/usr/local/tomcat/logs) на пользователя, которого вы хотите запустить. tomcat, чтобы обычные пользователи не могли писать в журнал после запуска.
Каталог tomcat в примере docker-образа принадлежит группе root.Если вы запускаете этот образ под обычным пользователем, вы не можете писать в лог. Однако это можно сделать, смонтировав каталог журналов, который будет упомянут в следующей статье о сборе журналов.
Бэйл
Последние файлы «корневого каталога» следующие:
tomcat_jdk8/
├── bin
│ ├── bash
│ ├── beep -> busybox
│ ├── blkid -> busybox
│ ├── ...
├── etc
│ ├── localtime
├── lib
│ └── x86_64-linux-gnu
│ └── libtinfo.so.5
└── usr
├── lib
│ └── locale
│ └── locale-archive
└── local
├── apache-tomcat-8.5.56
│ ...
├── config.yml
├── java -> jdk1.8.0_162
├── jdk1.8.0_162
│ ...
├── jmx_prometheus_javaagent-0.13.0.jar
└── tomcat -> apache-tomcat-8.5.56/
Убедившись, что все файлы готовы, мы можем упаковать каталог (здесь, tomcat_jdk8), и формат пакета должен быть tar/tar.gz/tar.xz и т. д.
Следует отметить, что эту операцию нельзя выполнить с помощью команды tar (может быть, я не знаю, как это сделать?), потому что tar должен быть запакован в родительский каталог, но тогда tar содержит имя каталога tomcat_jdk8. Это значит, что после распаковки в distroless файлы в нем будут лежать не прямо под корнем, а по-прежнему под tomcat_jdk8.
Поскольку tar не работает, используйте Python для упаковки. Неважно, если вы не знаете Python, просто следуйте за мной, и у вас не будет никаких проблем.
Сначала запустите образ python3, обратите внимание, чтобы сопоставить файл debian_file с каталогом /opt python3 (если у вас есть локальная среда python, вам не нужно так хлопотно).
docker run -it -v /root/tomcat_jdk8:/opt python:3.6
Затем выполните следующий код:
import tarfile, os
os.chdir("/opt")
tar = tarfile.open("/tmp/x.tar", "w")
for i in os.listdir("."):
tar.add(i)
tar.close()
Это упакует все файлы в tomcat_jdk8 в контейнер/tmp/x.tar
в файле. затем используйтеdocker cp
скопируй его на хост/tmp
вниз и сохраните его для последующего использования.
Хорошо, подготовка завершена. После остановки контейнера Python вы можете создать образ, разархивировав /tmp/x.tar в образ без дистрибутива.
сборка докерфайла
Мы можем делать образы как через dockerfile, так и через bazel. Сначала я буду использовать dockerfile, потому что он достаточно прост.
Создайте новый каталог:
mkdir dockerfiles
cd dockerfiles
После копирования /tmp/x.tar в текущий каталог создайте новыйDockerfile
документ:
FROM maxadd/distroless_base-debian10
ADD x.tar .
ENV JAVA_HOME=/usr/local/java LANG="en_US.utf8" PATH="/bin:/usr/local/java/bin"
EXPOSE 8080/tcp 12356/tcp
CMD ["/usr/local/start.sh"]
После копирования /tmp/x.tar в текущий каталог выполните команду сборки docker:
docker build -t tomcat:8-jdk8-distroless .
базал билд
Bazel — инструмент компиляции, запущенный Google, который используется для компиляции исходных кодов различных языков в бинарные файлы.Что касается преимуществ, то особых знаний у меня нет 😜. С этой точки зрения, компиляция образов докеров — это просто функция, которая идет вместе с ним, и это правда, он изначально не поддерживает компиляцию образов докеров.
Одним из больших преимуществ компиляции образов Docker с помощью bazel является то, что вам даже не нужно устанавливать Docker, но вам все равно придется установить его, если вы действительно хотите его использовать.
Печальная новость заключается в том, что использование bazel требует флипа, поэтому те, у кого нет этого средства, могут только извиниться.
Сначала установите базель:
# cat >/etc/yum.repos.d/bazel.repo <<'EOF'
[vbatts-bazel]
name=Copr repo for bazel owned by vbatts
baseurl=https://copr-be.cloud.fedoraproject.org/results/vbatts/bazel/epel-7-$basearch/
type=rpm-md
skip_if_unavailable=True
gpgcheck=1
EOF
# yum install bazel -y
Базель изначально не поддерживает компиляцию образов докеров, но GitHub имеетправило расширенияможет помочь вам завершить.
Сначала создайте каталог как WORKSPACE:
# mkdir bazel
Затем определите WORKSPACE, который является внешней зависимостью. На самом деле наша зависимость — это правило докера, так что просто загрузите его.
# cd bazel
# vim WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Download the rules_docker repository at release v0.14.3
http_archive(
name = "io_bazel_rules_docker",
sha256 = "6287241e033d247e9da5ff705dd6ef526bac39ae82f3d17de1b69f8cb313f9cd",
strip_prefix = "rules_docker-0.14.3",
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.14.3/rules_docker-v0.14.3.tar.gz"],
)
# OPTIONAL: Call this to override the default docker toolchain configuration.
# This call should be placed BEFORE the call to "container_repositories" below
# to actually override the default toolchain configuration.
# Note this is only required if you actually want to call
# docker_toolchain_configure with a custom attr; please read the toolchains
# docs in /toolchains/docker/ before blindly adding this to your WORKSPACE.
# BEGIN OPTIONAL segment:
load("@io_bazel_rules_docker//toolchains/docker:toolchain.bzl",
docker_toolchain_configure="toolchain_configure"
)
#docker_toolchain_configure(
# name = "docker_config",
# # OPTIONAL: Path to a directory which has a custom docker client config.json.
# # See https://docs.docker.com/engine/reference/commandline/cli/#configuration-files
# # for more details.
# client_config="<enter absolute path to your docker config directory here>",
# # OPTIONAL: Path to the docker binary.
# # Should be set explcitly for remote execution.
# docker_path="<enter absolute path to the docker binary (in the remote exec env) here>",
# # OPTIONAL: Path to the gzip binary.
# # Either gzip_path or gzip_target should be set explcitly for remote execution.
# gzip_path="<enter absolute path to the gzip binary (in the remote exec env) here>",
# # OPTIONAL: Bazel target for the gzip tool.
# # Either gzip_path or gzip_target should be set explcitly for remote execution.
# gzip_target="<enter absolute path (i.e., must start with repo name @...//:...) to an executable gzip target>",
# # OPTIONAL: Path to the xz binary.
# # Should be set explcitly for remote execution.
# xz_path="<enter absolute path to the xz binary (in the remote exec env) here>",
# # OPTIONAL: List of additional flags to pass to the docker command.
# docker_flags = [
# "--tls",
# "--log-level=info",
# ],
#
#)
# End of OPTIONAL segment.
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)
container_repositories()
# This is NOT needed when going through the language lang_image
# "repositories" function(s).
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
container_deps()
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_pull",
)
container_pull(
name = "base",
# 因为使用的是我上传到 dockerhub 上的 distroless 镜像,因此 registry 需要指定为下面的值
registry = "registry-1.docker.io",
repository = "maxadd/distroless_base-debian10",
)
Поскольку правила докера bazel часто обновляются, здесь я использую версию 0.14.3. Возможно, он скоро обновится, вам придется зайти на github и скопировать на него последние правила, иначе ваша сборка может дать сбой, потому что сборка bazel вроде бы тянет последние правила.
После определения зависимостей мы создаем пустой файл BUILD в каталоге, где находится WORKSPACE (поскольку этот файл будет проверен в процессе сборки), а затем создаем пакет для компиляции образа.
# touch BUILD
# mkdir tomcat
# mv /tmp/x.tar . # 将 tar 包移动到当前目录
# vim BUILD
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_image",
)
container_image(
name = "app",
base = "@base//image",
tars = ["x.tar"],
env = {
"PATH": "/bin:/usr/local/java/bin:/usr/local/java/jre/bin",
"JAVA_HOME": "/usr/local/java",
"LANG": "en_US.utf8"
},
workdir = "/usr/local/tomcat/webapps",
ports = ["8080", "12356"],
cmd = ["/usr/local/tomcat/start.sh"]
)
Начать компиляцию:
# cd ..
# bazel build //tomcat:app
//tomcat:app
это цель, которая представляет собой концепцию bazel, которая используется для указания того, какой каталог мы хотим скомпилировать. tomcat относится к созданному нами каталогу tomcat, потому что в нем есть файл BUILD, поэтому он также называется пакетом. app ссылается на файл BUILD вcontainer_image
Значение имени ниже, через//tomcat:app
найти его.
Компиляция подвержена ошибкам, и если вам не повезло сделать ошибку, вам придется разобраться с ней самостоятельно. После компиляции выполнить в текущем каталоге:
bazel-bin/tomcat/app.executable
Затем вы можете использовать изображения докеров, чтобы увидетьbazel/tomcat
Это зеркально, обратите внимание, что его тег — приложение, а не последний.
Его можно запускать, и он принципиально не отличается от образа, построенного докефайлом, лишь немного отличается.
запустить изображение
Независимо от того, как вы строите образ, он работает одинаково:
docker run --rm -it -e 'JAVA_OPTS=-Xmx200m -Xms200m -javaagent:/usr/local/jmx_prometheus_javaagent-0.13.0.jar=12356:/usr/local/config.yml' --cap-add=SYS_PTRACE -p 11111:12356 maxadd/tomcat:8-jdk8-distroless
зачем добавлять--cap-add=SYS_PTRACE
Это чтобы иметь возможность использовать такие команды, как jps.
Вы даже можете просмотреть его показатели производительности с помощью мониторинга jmx:
curl 127.0.0.1:11111/metrics
Хорошо, эта статья подходит к концу.На самом деле, использование bazel для создания изображений имеет свои преимущества, такие как высокая сила. Тем не менее, его по-прежнему очень сложно использовать в Китае, в том числе из-за отсутствия китайских документов и необходимости блокировать стену во время использования, для сравнения, рентабельность его использования слишком низкая.
Если бы я знал раньше, что команда Dockfile ADD может распаковывать tar-архивы, я бы все равно никогда этого не понял, поэтому у меня не так много информации о ее использовании. Если вы понимаете это естественно, если вы не знаете, как использовать dockerfile напрямую, все в порядке.