如何用Docker定制Ubuntu ISO镜像及解决Chroot网络问题
Hey there, let's break down your questions and work through solutions step by step—starting with the DNS issue blocking your chroot updates, then moving to the full Docker-based LiveCD customization workflow and chroot limitations.
1. Fixing DNS Resolution in the Chroot Environment
The DNS failure you're seeing happens because the chrooted environment doesn't inherit the container's DNS configuration. When you unsquash the filesystem, its /etc/resolv.conf is the default from the original Ubuntu ISO, which lacks valid DNS servers (that's why pinging IPs works, but domain lookups fail).
Here's the fix:
- Add this line to your
build_run_step2.sh, right before runningchroot edit/ ./buildscript.sh:# Copy the container's working DNS config into the chroot cp /etc/resolv.conf edit/etc/resolv.conf - This ensures the chroot uses the same DNS servers as your Docker container, which should resolve the "Temporary failure resolving" errors when running
apt-get update.
You can verify manually by entering the chroot and checking /etc/resolv.conf—it should have entries like nameserver 8.8.8.8 or your Docker daemon's default DNS servers.
2. Docker-Based LiveCD Customization Workflow & Chroot Limitations
Let's walk through the complete workflow, explain why your initial Dockerfile failed, and cover key Docker chroot restrictions.
Why Your Initial Dockerfile Failed
Docker's build process runs in a non-privileged environment by default. Operations like mounting loop devices (mount -o loop $ISO_FILE mnt), binding /dev//run, and using unsquashfs (which relies on loop devices under the hood) require elevated privileges. These will always fail during the docker build phase unless you enable privileged builds (not recommended for security and not widely supported).
Your build-run-commit approach is the right direction—moving privileged operations to the container runtime phase with --privileged.
Complete Workflow for Building & Exporting the Custom ISO
Here's a refined, end-to-end workflow:
Step 1: Build the Base Tooling Image
Create a Dockerfile that sets up all required tools and downloads/verifies the ISO (no privileged operations here):
FROM ubuntu:16.04 ENV ISO_FILE="ubuntu-16.04.3-desktop-amd64.iso" \ OS_VERSION="16.04.3" # Install dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ squashfs-tools genisoimage gnupg2 rsync wget curl nodejs \ build-essential libc6-dev-i386 # Create workspace directories RUN mkdir -p /root/workspace /data # Download and verify ISO WORKDIR /root/workspace RUN wget http://releases.ubuntu.com/$OS_VERSION/$ISO_FILE \ && wget http://releases.ubuntu.com/$OS_VERSION/SHA256SUMS \ && wget http://releases.ubuntu.com/$OS_VERSION/SHA256SUMS.gpg # Verify checksum and signature RUN /bin/bash -c "sha256sum -c <(grep $ISO_FILE SHA256SUMS)" RUN gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 0xFBB75451 0xEFE21092 RUN gpg2 --verify SHA256SUMS.gpg SHA256SUMS # Copy your scripts COPY bin/buildscript.sh bin/build_run_step2.sh /root/workspace/ RUN chmod +x buildscript.sh build_run_step2.sh
Build this image with:
docker build -t ubuntu-livecd-builder .
Step 2: Run the Privileged Container & Execute Customization
Run the container with --privileged (to allow mount/loop operations) and mount a local directory to export the final ISO:
docker run -it --privileged -v /path/to/your/output/folder:/data ubuntu-livecd-builder ./build_run_step2.sh
Update your build_run_step2.sh to include the DNS fix and add ISO repackaging steps at the end:
#!/bin/bash cd /root/workspace # Mount and extract ISO mount -o loop $ISO_FILE mnt rsync --exclude=/casper/filesystem.squashfs -a mnt/ extract-cd unsquashfs mnt/casper/filesystem.squashfs mv squashfs-root edit umount mnt # Fix DNS for chroot cp /etc/resolv.conf edit/etc/resolv.conf # Copy and run build script mv ./buildscript.sh edit/buildscript.sh mount -o bind /run/ edit/run mount --bind /dev/ edit/dev chroot edit/ ./buildscript.sh # Clean up chroot mounts umount edit/dev umount edit/run rm edit/buildscript.sh # -------------------------- # Repackage the custom ISO # -------------------------- # Update filesystem manifest and size chroot edit dpkg-query -W --showformat='${Package} ${Version}\n' > extract-cd/casper/filesystem.manifest mksquashfs edit extract-cd/casper/filesystem.squashfs -comp xz -b 1048576 du -sx --block-size=1 edit | cut -f1 > extract-cd/casper/filesystem.size # Generate new MD5 checksums cd extract-cd rm md5sum.txt find -type f -print0 | xargs -0 md5sum | grep -v isolinux/boot.cat | tee md5sum.txt # Build the final ISO (output to /data for host access) genisoimage -r -V "Custom Ubuntu Live 16.04" -cache-inodes -J -l \ -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot \ -boot-load-size 4 -boot-info-table \ -o /data/custom-ubuntu-16.04-live.iso .
Step 3: Retrieve the Custom ISO
After the container finishes running, your new ISO will be in the /path/to/your/output/folder directory on your host machine.
Key Docker Chroot Limitations
- Privilege Requirements: Chroot itself doesn't need privileges, but operations around it (mounting loop devices, binding
/proc//sys//dev) do. You must run the container with--privilegedor use granular capabilities like--cap-add=SYS_ADMIN(but--privilegedis simpler for this use case). - Isolation Overlap: Docker containers already provide filesystem and process isolation, so chroot adds a second layer of filesystem isolation—but the chrooted environment still inherits the container's network, cgroup limits, and kernel.
- Build Phase Restrictions: Privileged operations (like mounting) can't be done during
docker buildby default. You have to defer these to the runtime phase, which is why your initial Dockerfile failed.
内容的提问来源于stack exchange,提问作者user3074620

