mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-09 07:39:19 -05:00
168 lines
6.6 KiB
Markdown
168 lines
6.6 KiB
Markdown
# Using proxy in Docker builds
|
|
|
|
Docker builds can share proxy's package cache even when their builders and local
|
|
package caches are new. Configure the package manager inside the build to use
|
|
proxy. Cached archives still need to be downloaded from proxy and installed;
|
|
native extensions still need to be compiled.
|
|
|
|
## Run a persistent proxy
|
|
|
|
Run proxy outside the image build and keep its database and artifact storage
|
|
between builds. For a proxy running on your development machine:
|
|
|
|
```sh
|
|
PROXY_CACHE_METADATA=true proxy serve \
|
|
-listen :8080 \
|
|
-base-url http://host.docker.internal:8080 \
|
|
-storage-url "file://$PWD/proxy-cache/artifacts" \
|
|
-database-path ./proxy-cache/proxy.db
|
|
```
|
|
|
|
Docker Desktop provides `host.docker.internal` for reaching the host. On Linux
|
|
Docker Engine, add the host mapping when building:
|
|
|
|
```sh
|
|
docker build \
|
|
--add-host host.docker.internal=host-gateway \
|
|
--build-arg PROXY_URL=http://host.docker.internal:8080 \
|
|
-t app .
|
|
```
|
|
|
|
`localhost` inside a build refers to the build container. Both the build's proxy
|
|
URL and proxy's `base_url` must be reachable from that container, since some
|
|
registry responses contain download URLs derived from `base_url`. The proxy
|
|
must listen on an interface reachable from the builder, with access restricted
|
|
to the machines that should use it.
|
|
|
|
For CI or a remote builder, use a persistent service reachable from the builder,
|
|
such as `https://proxy.example.com`, and set proxy's `base_url` to that address.
|
|
Use the same service across jobs and pass its URL with `--build-arg PROXY_URL=...`.
|
|
Creating an empty proxy for every job loses the shared cache unless its database
|
|
and storage persist. If proxy runs in a container, mount persistent storage for
|
|
both. See [configuration](configuration.md) for storage and deployment options.
|
|
|
|
Metadata caching is optional, but avoids repeated metadata fetches within
|
|
`metadata_ttl`. Artifact caching is enabled by default. Proxy's configured
|
|
cooldown, denylist and scanning policies also apply to Docker builds.
|
|
|
|
## npm
|
|
|
|
In your Node build stage, copy the manifests before application source so an
|
|
unchanged dependency set can reuse Docker's installation layer:
|
|
|
|
```dockerfile
|
|
ARG PROXY_URL
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci --no-audit --no-fund --registry="${PROXY_URL:?PROXY_URL build arg required}/npm/"
|
|
COPY . .
|
|
```
|
|
|
|
Pass `PROXY_URL` without a trailing slash. With Docker Desktop:
|
|
|
|
```sh
|
|
docker build \
|
|
--build-arg PROXY_URL=http://host.docker.internal:8080 \
|
|
-t app .
|
|
```
|
|
|
|
Keep `node_modules` out of the build context so `COPY . .` does not overwrite
|
|
the installed dependencies. Lockfiles with custom registry or download URLs
|
|
may still direct requests to those hosts; check proxy's access log when using
|
|
private registries or non-registry dependencies. `--no-audit` skips the audit
|
|
request, which proxy would otherwise forward upstream.
|
|
|
|
## Ruby / Bundler
|
|
|
|
Keep `https://rubygems.org` as the source in your Gemfile and configure its mirror
|
|
inside the Ruby build stage. Install any system packages needed to compile
|
|
native extensions before this step:
|
|
|
|
```dockerfile
|
|
ARG PROXY_URL
|
|
COPY Gemfile Gemfile.lock ./
|
|
RUN bundle config set --local mirror.https://rubygems.org "${PROXY_URL:?PROXY_URL build arg required}/gem" \
|
|
&& bundle install \
|
|
&& bundle config unset --local mirror.https://rubygems.org
|
|
COPY . .
|
|
```
|
|
|
|
Use the same build command as the npm example. The mirror setting is removed
|
|
after installation so it is not retained in the image, but the URL still
|
|
appears in `docker history` because Docker records the build args used by `RUN`
|
|
lines. Keep credentials out of `PROXY_URL`. Exclude host Bundler
|
|
configuration and installed gems from the build context. Copy any local path
|
|
dependencies required by the Gemfile before `bundle install`.
|
|
|
|
The RubyGems mirror covers gems fetched from that source. Git dependencies and
|
|
other gem sources need their own configuration. Without
|
|
`mirror.https://rubygems.org.fallback_timeout`, `bundle install` fails if proxy
|
|
is unreachable. Setting it lets Bundler fall back to rubygems.org, so this setup
|
|
does not enforce network isolation either way.
|
|
|
|
## Layer caches and package caches
|
|
|
|
Keep existing Docker caching optimizations. If Docker reuses the installation
|
|
layer, the package manager does not run and proxy receives no requests. A
|
|
BuildKit cache mount can also preserve downloaded packages when that layer must
|
|
be rebuilt. For example, the npm step can use:
|
|
|
|
```dockerfile
|
|
RUN --mount=type=cache,target=/root/.npm \
|
|
npm ci --no-audit --no-fund --registry="${PROXY_URL:?PROXY_URL build arg required}/npm/"
|
|
```
|
|
|
|
Cache mounts are stored by the builder and are excluded from ordinary
|
|
`--cache-to` exports. Proxy can supply packages when a fresh builder has neither
|
|
the installation layer nor the package-manager cache. See Docker's
|
|
[cache guidance](https://docs.docker.com/build/cache/optimize/) and
|
|
[cache-mount reference](https://docs.docker.com/reference/dockerfile/#run---mounttypecache).
|
|
|
|
To check the configuration, enable proxy's JSONL log with `-access-log` and
|
|
rebuild with `docker build --no-cache`. Look for requests to `/npm/` or `/gem/`,
|
|
then repeat and check `proxy_cache_hits_total` on `/metrics`. Cache mounts still
|
|
retain their contents with `--no-cache`; omit them when testing proxy cache
|
|
hits. Upstream metadata revalidation can still occur.
|
|
|
|
## Base-image pulls
|
|
|
|
Package-manager configuration affects commands such as `npm ci` and
|
|
`bundle install`. To cache images referenced by `FROM`, configure a registry
|
|
mirror in the builder as well. For a proxy served at
|
|
`https://proxy.example.com`, put this in `buildkitd.toml`:
|
|
|
|
```toml
|
|
[registry."docker.io"]
|
|
mirrors = ["proxy.example.com"]
|
|
```
|
|
|
|
Create a Buildx builder with that configuration and select it explicitly:
|
|
|
|
```sh
|
|
docker buildx create --name proxy-builder \
|
|
--driver docker-container \
|
|
--buildkitd-config ./buildkitd.toml
|
|
|
|
docker buildx build --builder proxy-builder \
|
|
--build-arg PROXY_URL=https://proxy.example.com \
|
|
--load -t app .
|
|
```
|
|
|
|
For local Docker Desktop testing over HTTP, the configuration is:
|
|
|
|
```toml
|
|
[registry."docker.io"]
|
|
mirrors = ["host.docker.internal:8080"]
|
|
|
|
[registry."host.docker.internal:8080"]
|
|
http = true
|
|
```
|
|
|
|
The registry mirror address must be reachable from the BuildKit daemon itself.
|
|
The build's `--add-host` flag only adds a mapping inside build containers. A
|
|
separate Buildx builder has its own registry configuration; setting Docker
|
|
Engine's `registry-mirrors` does not configure that builder. See Docker's
|
|
[BuildKit configuration guide](https://docs.docker.com/build/buildkit/configure/).
|
|
|
|
Proxy's OCI endpoint is pull-only. BuildKit registry-cache exports with
|
|
`--cache-to type=registry` need a separate writable registry. Other cache export
|
|
backends can be used alongside proxy.
|