Контейнеры, которые сразу завершаются с exec format error, подталкивают к неверному инстинкту: добавить возможность, смонтировать устройство, изменить конфигурацию туннеля. Ни одно из этих действий не достигает проблемы. Ядро вообще не смогло выполнить бинарный файл, что в контейнере почти всегда означает, что образ рассчитан на другую архитектуру процессора, чем у хоста. Всё, что вы могли бы изменить в маршрутизации, учётных данных или привилегиях, происходит после запуска программы, а ни одна программа не запустилась.

Стартовое сообщение, которое выглядит как ошибка конфигурации

Сбой формата exec приходит от загрузчика, ещё до того как приложение прочитает хотя бы одну настройку. Поэтому он не создаёт ни предупреждений конфигурации, ни журнала туннеля, потому что нет живого процесса, который бы их записал. Сбой также на удивление быстрый, часто ещё до появления хотя бы одной строки в журнале контейнера. Одно и то же короткое сообщение появляется независимо от того, предназначен ли бинарный файл для другой архитектуры, другой операционной системы или повреждён.

Запишите среду выполнения и архитектуру вместе с точной ссылкой на образ, затем проверьте, что эта ссылка на самом деле предлагает. В Docker Desktop платформа контейнера принадлежит виртуальной машине Linux, а не ноутбуку, поэтому одной архитектуры хоста может быть недостаточно. Прочитайте список записей индекса для этой ссылки, а не маркетинговый текст на странице её тега.

Прочитайте индекс образа до команды запуска

Когда реестр публикует многоплатформенную ссылку, тег указывает на индекс, и каждая запись называет платформу со своим дайджестом. Изучайте рассматриваемую ссылку, а не соседний тег, и читайте индекс, вместо того чтобы предполагать его содержимое.

docker buildx imagetools inspect ghcr.io/example/vpn:1.4
docker image inspect --format '{{.Os}}/{{.Architecture}}' ghcr.io/example/vpn:1.4

Первая команда перечисляет платформы, которые публикует ссылка. Вторая сообщает платформу образа, уже присутствующего локально, и именно её запустит среда выполнения. Ссылка только с одной записью означает, что каждый хост получает один и тот же бинарный файл, и тег не поможет машине, для которой он никогда не собирался.

Теги выбирают вариант; они его не создают

Многоплатформенный индекс позволяет среде выполнения выбрать подходящую запись, что действительно удобно и часто путают с переносимостью. Выбор — это поиск, а не перевод: если варианта нет, выбирать нечего. Поэтому один и тот же тег на двух хостах может дать два разных бинарных файла, а на одном хосте не даёт ничего пригодного.

Закрепление по дайджесту устраняет неоднозначность и делает возможным более поздний обзор, потому что дайджест точно определяет протестированные байты. Храните этот дайджест вместе с записью о развёртывании, вместо того чтобы полагаться на тег, который случайно был актуальным.

Эмуляция — это договорённость, а не слой перевода

Эмуляция через поддерживаемую среду выполнения может запускать некоторые неродные нагрузки пользовательского пространства, поэтому абсолютное утверждение, что одна архитектура никогда не сможет запустить образ другой, неверно. Это также не общее решение. Эмулируемое выполнение имеет другие характеристики производительности, а тривиальный процесс, который запускается, ничего не говорит о том, ведёт ли себя нагрузка туннеля приемлемо.

Многоплатформенное руководство Docker рассматривает нативные сборки, кросс-компиляцию и эмуляцию как отдельные стратегии, и это правильный способ читать варианты. Выберите одну осознанно и проверьте нагрузку VPN в её рамках, вместо того чтобы предполагать эквивалентность.

Права решают другую проблему

Предоставление возможности администрирования сети или передача устройства TUN не может заставить несовместимый исполняемый файл работать. Это права среды выполнения, которые использует работающий процесс; они невидимы для загрузчика, который уже отказал файлу.

Обратное столь же верно. Нативный бинарный файл ничего не доказывает о привилегиях, доступе к устройствам, интеграции резолвера или политике перезапуска, которая нужна туннелю, поэтому контейнер, который запускается, ещё не контейнер, который работает. Сначала установите контракт платформы, затем переходите к контракту выполнения с его документированными опциями.

Храните дайджест образа, поддерживаемую цель и конфигурацию вместе в одной записи. Обновление тега, которое молча меняет архитектуру, легче поймать, когда предыдущий дайджест записан, чем когда единственный симптом — знакомая ошибка и новый день, потраченный на отладку.

Похожие статьи