无法通过 ssh 隧道推送到本地 docker 注册表

问题描述 投票:0回答:1

我租了一台服务器,想在上面托管我自己的 Docker 容器注册表。服务器使用Ubuntu 24.04,安装了docker和docker compose。

现在,我创建了这个 docker-compose.yml 来在服务器上运行注册表:

version: '3'
services:
  registry:
    image: registry:2
    ports:
      - "127.0.0.1:5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
    volumes:
      - ./data:/var/lib/registry

我正在使用

docker compose up
运行此程序。 然后我设置了从客户端到服务器的 ssh 隧道
ssh -L 5000:localhost:5000 user@server

现在,作为健全性检查,我在客户端上运行此命令:

$ curl -X GET http://127.0.0.1:5000/v2/_catalog
{"repositories":[]}

输出看起来很合理,是一个空的存储库列表。在服务器上,我正在运行不带

docker compose up
标志的
-d
,以查看日志输出,它显示:

registry-1  | time="2024-10-08T10:24:16.455126761Z" level=info msg="response completed" go.version=go1.20.8 http.request.host="127.0.0.1:5000" http.request.id=133d3573-9be6-48fe-9102-ffdac2706c93 http.request.method=GET http.request.remoteaddr="172.18.0.1:35336" http.request.uri="/v2/_catalog" http.request.useragent="curl/8.4.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.285188ms http.response.status=200 http.response.written=20 
registry-1  | 172.18.0.1 - - [08/Oct/2024:10:24:16 +0000] "GET /v2/_catalog HTTP/1.1" 200 20 "" "curl/8.4.0"

现在我想标记并推送图像。我在客户端上运行以下命令:

$ docker tag hello-world 127.0.0.1:5000/test:latest
$ docker push 127.0.0.1:5000/test:latest
The push refers to repository [127.0.0.1:5000/test]
Get "http://127.0.0.1:5000/v2/": dial tcp 127.0.0.1:5000: connect: connection refused

我也尝试用

localhost
而不是
127.0.0.1
来标记它,但结果是相同的。

为了彻底检查注册表是否正常工作,我在服务器上尝试了相同的操作:

root@Ubuntu-2404-noble-amd64-base ~ # docker tag hello-world 127.0.0.1:5000/test:latest
root@Ubuntu-2404-noble-amd64-base ~ # docker push 127.0.0.1:5000/test:latest
The push refers to repository [127.0.0.1:5000/test]
ac28800ec8bb: Pushed latest: digest: sha256:d37ada95d47ad12224c205a938129df7a3e52345828b4fa27b03a98825d1e2e7 size: 524

所以这有效,注册表似乎工作正常。作为另一个健全性检查,让我们在客户端上重复curl命令:

$ curl -X GET http://127.0.0.1:5000/v2/_catalog
{"repositories":["test"]}

所以这似乎正确地指向远程服务器上的 docker 注册表。 ssh 隧道似乎可以工作。 但是,可以在服务器上标记和推送图像的完全相同的命令会因客户端上的连接错误而失败。

我在客户端上使用MacOS。我在 Docker 引擎的设置中设置了不安全的注册表:

  "insecure-registries": [
    "127.0.0.1:5000",
    "localhost:5000"
  ]

此时我已不知所措。您能告诉我如何解决此问题吗?

docker docker-compose ssh docker-registry ssh-tunnel
1个回答
0
投票

建筑

+---------+                +---------+
| clientA |  ------------> | serverB |
+---------+                +---------+
macOS-Client               Ubuntu-2404-noble-amd64-base
                           yourServer Public IP
                           yourServerFQDN name

请确认以下有关您服务器的信息:

  • 您的服务器公共IP
  • 您的服务器 FQDN 名称
+---------+                              +---------+
| clientA |  ------------------------->  | serverB |
+---------+                              +---------+
                                              |
                                              | (docker-compose)
                       +----------------------+-----------------+
                       |port 443 (https)                        | port 5000
               +------------+                              +-----------------+
               |  Nginx     |   <--------------------->    | Docker Registry |
               +------------+                              +-----------------+
                       |  (Front-end)                           |  (Back-end)
                       +----------------------------------------+

下面以我内部环境的机器为例,所以IP和服务器FQDN名称都是示例。请根据您自己的 Sercer 设置进行调整。

以我为例:

  • 您的服务器公共IP(192.168.56.112)
  • 您的服务器 FQDN 名称 (demoserver.demo.local)

由于我没有DNS,为了简单起见,我直接修改了

/etc/hosts
的文件内容。

/etc/hosts

添加这是

/etc/hosts

192.168.56.112  demoserver.demo.local

(clientA和serverB都需要修改)

服务器B

创建一个目录

my_docker_registry
作为您的项目目录。

项目树

my_docker_registry <directory>
├── docker-compose.yml
├── my-demo-registry <directory>
│   ├── auth <directory>
│   │   └── htpasswd
│   └── data <directory>
└── nginx
    ├── certs <directory>
    ├── Dockerfile
    └── nginx.conf

配置注册表

所有指令均在

my_docker_registry
(项目根目录)中执行。

mkdir -p my-demo-registry/auth
mkdir -p my-demo-registry/data

添加用户名和密码

sudo apt install -y apache2-utils

# c create file
htpasswd -Bc my-demo-registry/auth/htpasswd demo01user

# second user do not create file
htpasswd -B my-demo-registry/auth/htpasswd demo02user

创建两个用户:

  • 演示01用户
  • 演示02用户

配置nginx

所有指令均在

my_docker_registry
(项目根目录)中执行。

mkdir -p nginx/certs

创建ssl证书

以下内容根据https://goharbor.io/docs/2.5.0/install-config/configure-https/的内容进行调整,生成ssl凭证。

以下将指令执行目录切换到nginx/certs目录。

cd nginx/certs

步骤01:生成CA证书私钥。

openssl genrsa -out ca.key 4096

步骤02:生成CA证书。

注意,请根据您设置的服务器的FQDN名称调整以下命令的内容(例如:

demoserver.demo.local
)。

openssl req -x509 -new -nodes -sha512 -days 3650 \
  -subj "/C=CN/ST=NewYork/L=NewYork/O=example/OU=Personal/CN=demoserver.demo.local" \
  -key ca.key \
  -out ca.crt

步骤03:生成服务器证书

步骤03-1:生成私钥。
openssl genrsa -out demoserver.demo.local.key 4096
步骤03-2:生成证书签名请求(CSR)。
openssl req -sha512 -new \
  -subj "/C=CN/ST=NewYork/L=NewYork/O=example/OU=Personal/CN=demoserver.demo.local" \
  -key demoserver.demo.local.key \
  -out demoserver.demo.local.csr
步骤03-3:生成x509 v3扩展文件。
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=demoserver.demo.local
DNS.2=demopc
DNS.3=localhost
EOF
步骤03-4:使用v3.ext文件为您的服务器主机生成证书。
openssl x509 -req -sha512 -days 3650 \
  -extfile v3.ext \
  -CA ca.crt \
  -CAkey ca.key \
  -CAcreateserial \
  -in demoserver.demo.local.csr \
  -out demoserver.demo.local.crt

步骤04:将demoserver.demo.local.crt转换为demoserver.demo.local.cert,供Docker使用。

openssl x509 \
  -inform PEM \
  -in demoserver.demo.local.crt \
  -out demoserver.demo.local.cert

步骤05:将服务器证书、密钥和CA文件复制到服务器主机上的Docker证书文件夹中。您必须首先创建适当的文件夹。

sudo mkdir -p /etc/docker/certs.d/demoserver.demo.local

sudo cp demoserver.demo.local.cert /etc/docker/certs.d/demoserver.demo.local/

sudo cp demoserver.demo.local.key /etc/docker/certs.d/demoserver.demo.local/

sudo cp ca.crt /etc/docker/certs.d/demoserver.demo.local/

sudo systemctl restart docker

nginx/Dockerfile

FROM nginx:alpine

COPY nginx.conf /etc/nginx/nginx.conf

RUN mkdir -p /etc/nginx/certs
COPY certs/demoserver.demo.local.crt /etc/nginx/certs/
COPY certs/demoserver.demo.local.key /etc/nginx/certs/

nginx/nginx.conf

events {
    worker_connections 1024;
}

http {
    server {
        listen 443 ssl;
        
        # Replace with your domain name
        server_name demoserver.demo.local;

        # SSL Certificate Path
        ssl_certificate /etc/nginx/certs/demoserver.demo.local.crt;
        
        # SSL key path
        ssl_certificate_key /etc/nginx/certs/demoserver.demo.local.key;

        location / {
            # Reverse proxy to Docker Registry
            # proxy_pass http://localhost:5000;
            proxy_pass http://registry:5000;
            
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

docker-compose.yml

version: '3.3'

services:
  registry:
    image: registry:2
    ports:
        # For internal access only
      - "5000:5000"  
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd      
    volumes:
      - ./my-demo-registry/auth:/auth
      - ./my-demo-registry/data:/var/lib/registry
# Data Volume      
#     - registry_data:/var/lib/registry  

  nginx:
    build: ./nginx
    ports:
      # Map to port 443 on the host
      - "443:443"
    depends_on:
      - registry

volumes:
  registry_data:

开始

docker-compose build

docker-compose up

检查

docker ps

您将看到两个容器正在执行。一个是

nginx
registry

测试

登录

docker login https://demoserver.demo.local

输入用户名和密码。 (我的例子:

demo01user

会回来

Login Succeeded

  • 拉你好世界
docker pull hello-world

docker tag hello-world demoserver.demo.local/demo01user/hello-world:0.0.1

docker push demoserver.demo.local/demo01user/hello-world:0.0.1
  • 列出图像
docker image ls

得到

REPOSITORY                                     TAG       IMAGE ID       CREATED         SIZE
...
demoserver.demo.local/demo01user/hello-world   0.0.1     d2c94e258dcb   17 months ago   13.3kB
hello-world                                    latest    d2c94e258dcb   17 months ago   13.3kB

clientA - 您的 macOS

  • 现在将 serverB 上的 nginx/certs 目录复制到您的 clientA 主机(您的 macOS

  • 执行以下指令

注意,macOS下相关说明可能需要调整。

sudo mkdir -p /etc/docker/certs.d/demoserver.demo.local
sudo cp demoserver.demo.local.cert /etc/docker/certs.d/demoserver.demo.local/
sudo cp demoserver.demo.local.key /etc/docker/certs.d/demoserver.demo.local/
sudo cp ca.crt /etc/docker/certs.d/demoserver.demo.local/
    
sudo systemctl restart docker

注意:这是在 clientA(即您的 macOS)上执行的。

由于我没有DNS,为了简单起见,我直接修改了

/etc/hosts
的文件内容。

/etc/hosts

添加这是

/etc/hosts

192.168.56.112  demoserver.demo.local

现在,在 clientA 上执行:

docker run demoserver.demo.local/demo01user/hello-world:0.0.1

您应该能够看到从serveB检索到的hello-world`的执行结果。

您也可以在本地机器上查看镜像。

docker image ls
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.