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

Add new option ADD_NO_CACHE_HEADER on requests to registry server #265

Merged
merged 1 commit into from
Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Some env options are available for use this interface for **only one server**.
- `READ_ONLY_REGISTRIES`: Desactivate dialog for remove and add new registries, available only when `SINGLE_REGISTRY=false`. (default: `false`).
- `SHOW_CATALOG_NB_TAGS`: Show number of tags per images on catalog page. This will produce + nb images requests, not recommended on large registries. (default: `false`).
- `HISTORY_CUSTOM_LABELS`: Expose custom labels in history page, custom labels will be processed like maintainer label.
- `USE_CONTROL_CACHE_HEADER`: Use `Control-Cache` header and set to `no-store, no-cache`. This will avoid some issues on multi-arch images (see [#260](https://github.com/Joxit/docker-registry-ui/issues/260)). This option requires registry configuration: `Access-Control-Allow-Headers` with `Cache-Control`. (default: `false`).

There are some examples with [docker-compose](https://docs.docker.com/compose/) and docker-registry-ui as proxy [here](https://github.com/Joxit/docker-registry-ui/tree/main/examples/ui-as-proxy/) or docker-registry-ui as standalone [here](https://github.com/Joxit/docker-registry-ui/tree/main/examples/ui-as-standalone/).

Expand All @@ -128,7 +129,7 @@ http:
headers:
Access-Control-Allow-Origin: ['http://registry.example.com']
Access-Control-Allow-Credentials: [true]
Access-Control-Allow-Headers: ['Authorization', 'Accept']
Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS'] # Optional
```

Expand All @@ -150,7 +151,7 @@ And you need to add these HEADERS:
http:
headers:
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization', 'Accept']
Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
Access-Control-Expose-Headers: ['Docker-Content-Digest']
```

Expand Down Expand Up @@ -178,7 +179,7 @@ http:
X-Content-Type-Options: [nosniff]
Access-Control-Allow-Origin: ['http://127.0.0.1:8000']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Headers: ['Authorization', 'Accept']
Access-Control-Allow-Headers: ['Authorization', 'Accept', 'Cache-Control']
Access-Control-Max-Age: [1728000]
Access-Control-Allow-Credentials: [true]
Access-Control-Expose-Headers: ['Docker-Content-Digest']
Expand Down
1 change: 1 addition & 0 deletions bin/90-docker-registry-ui.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ sed -i "s~\${DEFAULT_REGISTRIES}~${DEFAULT_REGISTRIES}~" index.html
sed -i "s~\${READ_ONLY_REGISTRIES}~${READ_ONLY_REGISTRIES}~" index.html
sed -i "s~\${SHOW_CATALOG_NB_TAGS}~${SHOW_CATALOG_NB_TAGS}~" index.html
sed -i "s~\${HISTORY_CUSTOM_LABELS}~${HISTORY_CUSTOM_LABELS}~" index.html
sed -i "s~\${USE_CONTROL_CACHE_HEADER}~${USE_CONTROL_CACHE_HEADER}~" index.html

if [ -z "${DELETE_IMAGES}" ] || [ "${DELETE_IMAGES}" = false ] ; then
sed -i "s/\${DELETE_IMAGES}/false/" index.html
Expand Down
3 changes: 3 additions & 0 deletions src/components/docker-registry-ui.riot
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
on-notify="{ notifySnackbar }"
filter-results="{ state.filter }"
on-authentication="{ onAuthentication }"
use-control-cache-header="{ truthy(props.useControlCacheHeader) }"
></tag-list>
</route>
<route path="{baseRoute}taghistory/(.*)">
Expand All @@ -65,6 +66,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
on-notify="{ notifySnackbar }"
on-authentication="{ onAuthentication }"
history-custom-labels="{ stringToArray(props.historyCustomLabels) }"
use-control-cache-header="{ truthy(props.useControlCacheHeader) }"
></tag-history>
</route>
</router>
Expand Down Expand Up @@ -133,6 +135,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
this.state.name = props.name || stripHttps(props.registryUrl);
this.state.catalogElementsLimit = props.catalogElementsLimit || 100000;
this.state.pullUrl = this.pullUrl(this.state.registryUrl, props.pullUrl);
this.state.useControlCacheHeader = props.useControlCacheHeader;
},
onServerChange(registryUrl) {
this.update({
Expand Down
4 changes: 3 additions & 1 deletion src/components/tag-history/tag-history.riot
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
registryUrl: props.registryUrl,
onNotify: props.onNotify,
onAuthentication: props.onAuthentication,
useControlCacheHeader: props.useControlCacheHeader,
});
state.image.fillInfo();
},
Expand All @@ -66,14 +67,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
},
onTabChanged(arch, idx) {
const state = this.state;
const { registryUrl, onNotify } = this.props;
const { registryUrl, onNotify, useControlCacheHeader } = this.props;
state.elements = [];
state.image.variants[idx] =
state.image.variants[idx] ||
new DockerImage(this.props.image, arch.digest, {
list: false,
registryUrl,
onNotify,
useControlCacheHeader,
});
if (state.image.variants[idx].blobs) {
return this.processBlobs(state.image.variants[idx].blobs);
Expand Down
1 change: 1 addition & 0 deletions src/components/tag-list/tag-list.riot
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
registryUrl: props.registryUrl,
onNotify: props.onNotify,
onAuthentication: props.onAuthentication,
useControlCacheHeader: props.useControlCacheHeader,
})
)
.sort(compare);
Expand Down
2 changes: 2 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
read-only-registries="${READ_ONLY_REGISTRIES}"
show-catalog-nb-tags="${SHOW_CATALOG_NB_TAGS}"
history-custom-labels="${HISTORY_CUSTOM_LABELS}"
use-control-cache-header="${USE_CONTROL_CACHE_HEADER}"
>
</docker-registry-ui>
<!-- endbuild -->
Expand All @@ -60,6 +61,7 @@
single-registry="false"
show-catalog-nb-tags="true"
history-custom-labels="first_custom_labels,second_custom_labels"
use-control-cache-header="false"
>
</docker-registry-ui>
<!-- endbuild -->
Expand Down
10 changes: 8 additions & 2 deletions src/scripts/docker-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function compare(e1, e2) {
}

export class DockerImage {
constructor(name, tag, { list, registryUrl, onNotify, onAuthentication }) {
constructor(name, tag, { list, registryUrl, onNotify, onAuthentication, useControlCacheHeader }) {
this.name = name;
this.tag = tag;
this.chars = 0;
Expand All @@ -55,6 +55,7 @@ export class DockerImage {
registryUrl,
onNotify,
onAuthentication,
useControlCacheHeader,
};
this.ociImage = false;
observable(this);
Expand Down Expand Up @@ -143,6 +144,9 @@ export class DockerImage {
'application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json' +
(self.opts.list ? ', application/vnd.docker.distribution.manifest.list.v2+json' : '')
);
if (self.opts.useControlCacheHeader) {
oReq.setRequestHeader('Cache-Control', 'no-store, no-cache');
}
oReq.send();
}
getBlobs(blob) {
Expand All @@ -165,7 +169,9 @@ export class DockerImage {
self.trigger('creation-date', self.creationDate);
self.trigger('blobs', self.blobs);
} else if (this.status === 404) {
self.opts.onNotify(`Blobs for ${self.name}:${self.tag} not found`, true);
self.opts.onNotify(`Blobs for ${self.name}:${self.tag} not found: blob '${self.blobs}'`, true);
} else if (!this.responseText) {
self.opts.onNotify(`Can"t get blobs for ${self.name}:${self.tag}: blob '${self.blobs}' (no message error)`, true);
} else {
self.opts.onNotify(this.responseText);
}
Expand Down