Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't update image if local repository changes #13

Open
aidan-gallagher opened this issue May 15, 2024 · 1 comment
Open

Don't update image if local repository changes #13

aidan-gallagher opened this issue May 15, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@aidan-gallagher
Copy link
Owner

aidan-gallagher commented May 15, 2024

The dockerfile has

  • Remote apt repositories.
  • Local apt repositories

If the remote apt repositories change then the docker image doesn't have to be rebuilt (however it can be rebuilt with --no-cache).
If the local apt repository changes then the docker image must be rebuilt (because it uses COPY).

This is problematic because:

  • Some users have a workflow where they have --local-repository and --destination as the same directory to allow them to build multiple repositories that depend on each other. This is problematic because if you build repo1 successfully it deposits the .debs into it's local repository and invalidates it's cache.
  • The user may want to just run "apt update && apt upgrade" for faster updating rather than rebuilding the image.

The local repository stage must happen at build time before other dependencies are installed because a dependency in the control file might only exist in the local repository.

@aidan-gallagher
Copy link
Owner Author

aidan-gallagher commented May 15, 2024

Here are some ideas to consider:

Option 1 (AI)

To address the issue of Docker rebuilding the image every time the local repository changes, we could separate the build of the local repository from the rest of the Dockerfile.

  1. Separate the Local Repository from the Main Dockerfile
    Create a separate Dockerfile just for building the local repository. This will be a multi-stage build where the first stage generates the local repository, and the second stage uses this repository to install the packages.

  2. Create a Dockerfile for the Local Repository
    Create a Dockerfile.localrepo to handle the local repository setup.

# Dockerfile.localrepo
FROM debian:latest AS localrepo

# Set up working directory for the local repo
WORKDIR /localrepo

# Copy .deb files into the container
COPY your-debs-directory/ ./

# Generate the Packages.gz file
RUN apt-get update && \
    apt-get install -y apt-utils && \
    apt-ftparchive packages . | gzip -c > Packages.gz

# Expose the repository directory as a volume
VOLUME /localrepo
  1. Build the Local Repository Image
    Build this local repository image.
docker build -t localrepo:latest -f Dockerfile.localrepo .
  1. Modify the main Dockerfile to copy files from the local repository built in the first step.
# Dockerfile
FROM debian:latest

# Add the remote repositories
RUN echo "deb http://some-remote-repo/ stable main" > /etc/apt/sources.list.d/remote-repo.list

# Copy the local repository files from the localrepo image
COPY --from=localrepo /localrepo /localrepo

# Add the local repository to the sources.list
RUN echo "deb [trusted=yes] file:///localrepo ./" > /etc/apt/sources.list.d/localrepo.list

# Update and install necessary tools
RUN apt-get update && \
    apt-get install -y your-tools
6. Build Your Main Docker Image
Now build your main Docker image.

docker build -t yourimage:latest .
  • Dockerfile.localrepo: This Dockerfile is dedicated to creating the local repository. It copies the .deb files into the container, generates the Packages.gz file, and exposes the repository directory as a volume. This allows us to change the local repository without rebuilding your entire main Docker image.

  • Main Dockerfile: This Dockerfile builds your main application image. It adds the local repository by copying files from the localrepo image and updates the package sources list accordingly.
    By separating the build process of the local repository, we only need to rebuild the local repository image when the .deb files change. The main application image can then reuse the updated local repository without rebuilding from scratch unless necessary.

Option 2 v1

We could add another CLI flag (e.g --local-repository-update-only).

--local-repository would still be required for the first build. However if the user only wanted to update dependencies using "apt update && apt upgrade" then --local-repository-update-only would be mounted at run time but not copied at build time.

This puts the onus on the user and maybes makes the CLI options a bit more confusing.

debpic --local-repository ~/mydebs
debpic --local-repository ~/my_debs --local-repository-update-only ~/my_updated_debs

This idea is rejected but I'll leave it here in case it helps generate new ideas.

Option 2 v2

Add another CLI flag --update-only which will not rebuild the image but it will run apt update && apt upgrade and then write the image.

  1. Run debpic as normal once to create image
  • If --update-only is specified but no image exists then give warning and ignore flag.
  1. Update dependencies through remote apt server or --local-repository
  2. Run debpic --update-only. Under the hood this will:
  • Skip the "docker build" stage and go to "docker run" (without the --rm flag?)
  • "Docker run" will mount the --local-repository to /tmp/local_repository.
  • Within the container it will run "sudo apt update && sudo apt upgrade"
  • docker commit container_ID image_ID
  • docker rm container
  1. subsequent runs will have to use "--update-only" too otherwise they will call "docker build" which may take some time and will overwrite the existing image.

@aidan-gallagher aidan-gallagher added the enhancement New feature or request label May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant