The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8 from apt-get update means a repository line was added without the key that signs that repository. Download the repository's key into /etc/apt/keyrings and point the line at it with signed-by=; the next update reads the feed.

In the test the line for Docker's Ubuntu feed had no key at all. After the key was saved as /etc/apt/keyrings/docker.asc and the line gained signed-by=/etc/apt/keyrings/docker.asc, apt-get update fetched the feed's package list and returned 0.

The error

$ echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list
exit code: 0
$ apt-get update
Get:1 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Err:1 https://download.docker.com/linux/ubuntu noble InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
Hit:2 http://archive.ubuntu.com/ubuntu noble InRelease
...
Reading package lists...
W: GPG error: https://download.docker.com/linux/ubuntu noble InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
E: The repository 'https://download.docker.com/linux/ubuntu noble InRelease' is not signed.
exit code: 100

Why it happens

apt downloaded the repository's InRelease file, which carries a signature, and found no key on the machine that matched it. The key file downloaded for the fix, read with gpg --show-keys, held one key with the user ID Docker Release (CE deb); with it in place the NO_PUBKEY line did not come back. Because the signature could not be checked, apt printed is not signed as an E: line, refused the repository and returned exit code 100. The Ubuntu sources in the same run still showed Hit:, so one bad line is enough to fail the whole command.

The fix

$ install -m 0755 -d /etc/apt/keyrings
exit code: 0
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
exit code: 0
$ echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list
exit code: 0
$ apt-get update
Get:1 https://download.docker.com/linux/ubuntu noble InRelease [48.5 kB]
Hit:2 http://archive.ubuntu.com/ubuntu noble InRelease
Get:3 https://download.docker.com/linux/ubuntu noble/stable amd64 Packages [89.1 kB]
...
Reading package lists...
exit code: 0
$ apt-cache policy docker-ce-cli | head -3
docker-ce-cli:
  Installed: (none)
  Candidate: 5:29.9.3-1~ubuntu.24.04~noble
exit code: 0

Two things changed: the key file now exists, and the list line names it in signed-by=, so apt checks this repository against that one key. The Packages line for the Docker feed appeared and apt-cache policy showed a candidate version from it. For another vendor's feed, use the key URL that vendor publishes for its repository. The older way, piping the key into apt-key add, also made the update pass in the test, but apt printed a deprecation warning for it; see the related post linked below.

How it was reproduced

The capture was made in an ubuntu:24.04 container (Ubuntu 24.04.5 LTS, apt 2.8.3) on Docker Engine 29.9.3, standing in for Ubuntu in WSL. As root, a list file for Docker's noble stable feed was written without a key and apt-get update was run, in a container where gnupg, curl and ca-certificates had been installed beforehand as a set-up step; then the key was downloaded, the line was rewritten with signed-by= and the update was run again.

Frequently asked

How do I fix NO_PUBKEY in apt-get update?
Download the repository's signing key into /etc/apt/keyrings and add signed-by= with that file path to the repository line. In the test apt-get update then fetched the Docker feed and returned 0.
What does 'The repository is not signed' mean in apt?
In the test it followed the NO_PUBKEY line: apt could not check the InRelease signature because the key was missing, refused that repository and returned exit code 100.
Does NO_PUBKEY stop apt-get update for the other repositories?
In the test the Ubuntu sources still showed Hit lines, but the command ended with the E: line for the unsigned repository and returned exit code 100.

More decoded errors in the Fixes category. If apt prints a warning about trusted.gpg after you added a key the old way, see Key is stored in legacy trusted.gpg keyring.