代码之家  ›  专栏  ›  技术社区  ›  srghma

自定义存储(在chroot内部)的nix在docker容器中不工作-无法解析主机:docker

  •  0
  • srghma  · 技术社区  · 7 年前

    https://github.com/NixOS/nix/issues/2663


    1. 在某个终端运行这个

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

    1. 保存测试文件
    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
    
    
    1. 没有它也能工作 --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

    1. 它不适用于 --储存 论点
    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

    如何让它工作?


    更新:

    --储存

    不幸的是,尼克斯不允许我自己创作( touch /etc/nsswitch.conf 引发权限被拒绝)


    更新:

    我发现我可以用 extra-sandbox-paths

    安装/等/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 回复  |  直到 7 年前
        1
  •  1
  •   Charles Duffy    7 年前

    installPhase curl :使它们的输出仅依赖于它们所声明的输入,而不依赖于其它任何输入。连接到网络的派生从本质上讲是不纯洁的:其结果将取决于在调用时给定网络资源背后存在的内容。因此,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 只使用纯Nix代码构建与Docker兼容的映像,而不是尝试在Nix派生中运行Docker。