nix с пользовательским хранилищем (внутри chroot) не работает в контейнере Docker - не удалось разрешить host: docker - PullRequest
0 голосов
/ 02 февраля 2019

возникла проблема https://github.com/NixOS/nix/issues/2663


Как воспроизвести

  1. запустить это на каком-нибудь терминале

docker run --privileged --rm --name some-docker docker:stable-dind

сохранить тестовый файл
cat > /tmp/test.nix << 'EOL'
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
stdenv.mkDerivation {
  pname = "test";
  version = "0.0.1";
  DOCKER_HOST = builtins.getEnv "DOCKER_HOST";
  buildInputs = [docker curl nettools];
  phases = "installPhase";
  installPhase = ''
    (ls -al /etc || true)
    (cat /etc/nsswitch.conf || true)
    (cat /etc/hosts || true)
    (cat /etc/resolv.conf || true)

    # without --store returns
    #
    # Kernel IP routing table
    # Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
    # 0.0.0.0         172.17.0.1      0.0.0.0         UG        0 0          0 eth0
    # 172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
    #
    # with --store returns empty
    #
    # Kernel IP routing table
    # Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
    netstat --numeric --route

    # without --store - returns without error
    # with --store - error "Could not resolve host: docker"
    curl -v http://docker:2375/v1.39/version

    # without --store - returns without error, prints server info
    # with --store - error "error during connect: Get http://docker:2375/v1.39/version: dial tcp: lookup docker on [::1]:53: read udp [::1]:39506->[::1]:53: read: connection refused"
    docker version

    # create dummy package if everything above did work fine
    mkdir -p $out
  '';
}
EOL

работает без аргумента --store
docker run -it --rm --link some-docker:docker -v /tmp/test.nix:/tmp/test.nix nixos/nix@sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357 sh -c 'export DOCKER_HOST=tcp://docker:2375/ && (echo "hosts: files dns" > /etc/nsswitch.conf) && nix-build /tmp/test.nix'

вывод - https://pastebin.com/DZmXrATR

не работает с --store аргументом
docker run -it --rm --link some-docker:docker --privileged -v /tmp/test.nix:/tmp/test.nix nixos/nix@sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357 sh -c 'export DOCKER_HOST=tcp://docker:2375/ && (echo "hosts: files dns" > /etc/nsswitch.conf) && nix-build --store /tmp/store /tmp/test.nix'

выводом https://pastebin.com/Z4DxtLQr

как заставить это работать?


Обновление:

похоже, потому что /etc/nsswitch.conf не монтируется при использовании --store

К сожалению, nix не позволяет мне создать его самому (touch /etc/nsswitch.conf выбрасывает разрешение запрещено)


Обновление:

Я обнаружил, что могу использовать extra-sandbox-paths для монтирования файлов из контейнера в песочницу nix-build

монтирование /etc/nsswitch.conf решено curl: (6) Could not resolve host: docker

но я не могу исправить ошибку * Immediate connect fail for 172.17.0.2: Network is unreachable, я попытался смонтировать все связанные с сетью файлы из / etc, но он не работает

docker run --privileged --rm --name some-docker docker:stable-dind

docker run -it --rm --link some-docker:docker --privileged -v /tmp/test.nix:/tmp/test.nix nixos/nix@sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357 sh

nix-env -i curl nettools

# works
curl -v http://172.17.0.2:2375/v1.39/version

# works
curl -v http://docker:2375/v1.39/version

# lo and eth
ifconfig -a

# not empty
netstat -rn

export DOCKER_HOST=tcp://docker:2375/ && (echo "hosts: files dns" > /etc/nsswitch.conf)

cat > /etc/nix/nix.conf << 'EOL'
sandbox = false
extra-sandbox-paths = /etc/nsswitch.conf=/etc/nsswitch.conf /etc/resolv.conf=/etc/resolv.conf /etc/hosts=/etc/hosts /etc/protocols=/etc/protocols /etc/udhcpd.conf=/etc/udhcpd.conf /etc/modules=/etc/modules
EOL

cat > /tmp/test.nix << 'EOL'
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
stdenv.mkDerivation {
  pname = "test";
  version = "0.0.1";
  DOCKER_HOST = builtins.getEnv "DOCKER_HOST";
  buildInputs = [docker curl nettools];
  phases = "installPhase";
  installPhase = ''
    # only lo
    ifconfig -a

    # empty
    netstat --numeric --route

    # fails
    curl -v http://172.17.0.2:2375/v1.39/version
    curl -v http://docker:2375/v1.39/version

    docker version
    mkdir -p $out
  '';
}
EOL

nix-build --store /tmp/store /tmp/test.nix

ОБНОВЛЕНИЕ

Текущее состояние исследований

https://gitlab.com/gitlab-org/gitlab-ce/issues/31312#note_138576414

1 Ответ

0 голосов
/ 04 февраля 2019

Если ваш installPhase работает curl, вы делаете это неправильно.Предполагается, что деривации в Nix pure : их вывод зависит только от заявленных входных данных и ничего более.Деривация, которая подключается к сети, нечиста по своей природе: ее результаты будут зависеть от того, что находится за данным сетевым ресурсом в тот момент, когда он вызывается.Таким образом, песочница Nix намеренно (и в соответствии с ее документацией) запрещает доступ к сети его создателям.

Рассмотрим следующее, которое все еще нечисто, но использует вместо него builtins.fetchurl и поэтому не заблокировано для работы:

{ pkgs ? import <nixpkgs> {} }:
with pkgs; let
  # WARNING: This is impure; usually, downloads should include an explicit hash
  versionFile = builtins.fetchurl http://172.17.0.2:2375/v1.39/version
in stdenv.mkDerivation {
  pname = "test";
  version = "0.0.1";
  DOCKER_HOST = builtins.getEnv "DOCKER_HOST";
  buildInputs = [docker curl nettools];
  phases = "installPhase";
  installPhase = ''
    cat ${escapeShellArg versionFile}
    docker version
    mkdir -p "$out"
  '';
}

Настоятельно рекомендуется использовать pkgs.dockerTools для создания совместимых с Docker образов с использованием только чистого кода Nix, а не пытаться запускать Docker внутри деривации Nix.

...