Merge pull request #128 from justincormack/resolvconf-init

In the init section use a symlink for /etc/resolv.conf
This commit is contained in:
Justin Cormack 2017-07-25 15:39:34 +01:00 committed by GitHub
commit 36217e5145
2 changed files with 40 additions and 19 deletions

View File

@ -40,6 +40,12 @@ RUN rm -f Dockerfile
ENTRYPOINT ["/sbin/tini", "--", "/bin/rc.init"] ENTRYPOINT ["/sbin/tini", "--", "/bin/rc.init"]
` `
// For now this is a constant that we use in init section only to make
// resolv.conf point at somewhere writeable. In future whe we are not using
// Docker to extract images we can read this directly from image, but now Docker
// will overwrite anything we put in the image.
const resolvconfSymlink = "/run/resolvconf/resolv.conf"
var additions = map[string]addFun{ var additions = map[string]addFun{
"docker": func(tw *tar.Writer) error { "docker": func(tw *tar.Writer) error {
log.Infof(" Adding Dockerfile") log.Infof(" Adding Dockerfile")
@ -146,7 +152,7 @@ func Build(m Moby, w io.Writer, pull bool, tp string) error {
// get kernel and initrd tarball from container // get kernel and initrd tarball from container
log.Infof("Extract kernel image: %s", m.Kernel.Image) log.Infof("Extract kernel image: %s", m.Kernel.Image)
kf := newKernelFilter(iw, m.Kernel.Cmdline, m.Kernel.Binary, m.Kernel.Tar) kf := newKernelFilter(iw, m.Kernel.Cmdline, m.Kernel.Binary, m.Kernel.Tar)
err := ImageTar(m.Kernel.Image, "", kf, enforceContentTrust(m.Kernel.Image, &m.Trust), pull) err := ImageTar(m.Kernel.Image, "", kf, enforceContentTrust(m.Kernel.Image, &m.Trust), pull, "")
if err != nil { if err != nil {
return fmt.Errorf("Failed to extract kernel image and tarball: %v", err) return fmt.Errorf("Failed to extract kernel image and tarball: %v", err)
} }
@ -162,7 +168,7 @@ func Build(m Moby, w io.Writer, pull bool, tp string) error {
} }
for _, ii := range m.Init { for _, ii := range m.Init {
log.Infof("Process init image: %s", ii) log.Infof("Process init image: %s", ii)
err := ImageTar(ii, "", iw, enforceContentTrust(ii, &m.Trust), pull) err := ImageTar(ii, "", iw, enforceContentTrust(ii, &m.Trust), pull, resolvconfSymlink)
if err != nil { if err != nil {
return fmt.Errorf("Failed to build init tarball from %s: %v", ii, err) return fmt.Errorf("Failed to build init tarball from %s: %v", ii, err)
} }

View File

@ -22,6 +22,11 @@ type tarWriter interface {
// used the containerd libraries to do this instead locally direct from a local image // used the containerd libraries to do this instead locally direct from a local image
// cache as it would be much simpler. // cache as it would be much simpler.
// Unfortunately there are some files that Docker always makes appear in a running image and
// export shows them. In particular we have no way for a user to specify their own resolv.conf.
// Even if we were not using docker export to get the image, users of docker build cannot override
// the resolv.conf either, as it is not writeable and bind mounted in.
var exclude = map[string]bool{ var exclude = map[string]bool{
".dockerenv": true, ".dockerenv": true,
"Dockerfile": true, "Dockerfile": true,
@ -39,10 +44,8 @@ ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes ff02::1 ip6-allnodes
ff02::2 ip6-allrouters ff02::2 ip6-allrouters
`, `,
"etc/resolv.conf": `nameserver 8.8.8.8 "etc/resolv.conf": `
nameserver 8.8.4.4 # no resolv.conf configured
nameserver 2001:4860:4860::8888
nameserver 2001:4860:4860::8844
`, `,
} }
@ -75,7 +78,7 @@ func tarPrefix(path string, tw tarWriter) error {
} }
// ImageTar takes a Docker image and outputs it to a tar stream // ImageTar takes a Docker image and outputs it to a tar stream
func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool) error { func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool, resolv string) error {
log.Debugf("image tar: %s %s", image, prefix) log.Debugf("image tar: %s %s", image, prefix)
if prefix != "" && prefix[len(prefix)-1] != byte('/') { if prefix != "" && prefix[len(prefix)-1] != byte('/') {
return fmt.Errorf("prefix does not end with /: %s", prefix) return fmt.Errorf("prefix does not end with /: %s", prefix)
@ -137,17 +140,29 @@ func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool) error {
return err return err
} }
} else if replace[hdr.Name] != "" { } else if replace[hdr.Name] != "" {
contents := replace[hdr.Name] if hdr.Name != "etc/resolv.conf" || resolv == "" {
hdr.Size = int64(len(contents)) contents := replace[hdr.Name]
hdr.Name = prefix + hdr.Name hdr.Size = int64(len(contents))
log.Debugf("image tar: %s %s add %s", image, prefix, hdr.Name) hdr.Name = prefix + hdr.Name
if err := tw.WriteHeader(hdr); err != nil { log.Debugf("image tar: %s %s add %s", image, prefix, hdr.Name)
return err if err := tw.WriteHeader(hdr); err != nil {
} return err
buf := bytes.NewBufferString(contents) }
_, err = io.Copy(tw, buf) buf := bytes.NewBufferString(contents)
if err != nil { _, err = io.Copy(tw, buf)
return err if err != nil {
return err
}
} else {
// replace resolv.conf with specified symlink
hdr.Name = prefix + hdr.Name
hdr.Size = 0
hdr.Typeflag = tar.TypeSymlink
hdr.Linkname = resolv
log.Debugf("image tar: %s %s add resolv symlink /etc/resolv.conf -> %s", image, prefix, resolv)
if err := tw.WriteHeader(hdr); err != nil {
return err
}
} }
_, err = io.Copy(ioutil.Discard, tr) _, err = io.Copy(ioutil.Discard, tr)
if err != nil { if err != nil {
@ -171,7 +186,7 @@ func ImageTar(image, prefix string, tw tarWriter, trust bool, pull bool) error {
// ImageBundle produces an OCI bundle at the given path in a tarball, given an image and a config.json // ImageBundle produces an OCI bundle at the given path in a tarball, given an image and a config.json
func ImageBundle(path string, image string, config []byte, tw tarWriter, trust bool, pull bool) error { func ImageBundle(path string, image string, config []byte, tw tarWriter, trust bool, pull bool) error {
log.Debugf("image bundle: %s %s cfg: %s", path, image, string(config)) log.Debugf("image bundle: %s %s cfg: %s", path, image, string(config))
err := ImageTar(image, path+"/rootfs/", tw, trust, pull) err := ImageTar(image, path+"/rootfs/", tw, trust, pull, "")
if err != nil { if err != nil {
return err return err
} }