老师的 Docker Hub

Viewed 7

老师的 Docker Hub 🐳

快速启动

docker compose up -d

端口一览

端口 服务 说明
5000 mirror Pull-through 缓存(拉镜像用这个)
5001 private 私有仓库(推镜像用这个)
8080 UI 浏览器打开看镜像列表

拉镜像(pull-through cache)

方式一:直接指定仓库地址

# 拉 Docker Hub 官方镜像
docker pull localhost:5000/library/nginx:latest
docker pull localhost:5000/library/ubuntu:22.04

# 拉第三方镜像(格式:localhost:5000/<用户>/<镜像>:<tag>)
docker pull localhost:5000/bitnami/redis:latest

方式二:配置 daemon.json(推荐,之后 docker pull 照常写)

编辑 /etc/docker/daemon.json(Mac 在 Docker Desktop → Settings → Docker Engine):

{
  "registry-mirrors": ["http://localhost:5000"]
}

然后重启 Docker:

sudo systemctl restart docker   # Linux
# Mac/Windows:重启 Docker Desktop

配置后直接用正常命令:

docker pull nginx:latest   # 自动走 mirror

推镜像(私有仓库)

# 打 tag(指向本地私有仓库 5001 端口)
docker tag myapp:v1 localhost:5001/myapp:v1

# 推送
docker push localhost:5001/myapp:v1

# 拉回来
docker pull localhost:5001/myapp:v1

开启密码认证(可选)

  1. 生成 htpasswd 文件:
mkdir -p ./auth
docker run --rm --entrypoint htpasswd httpd:2 \
  -Bbn teacher secret123 > ./auth/htpasswd
  1. config/registry-push.yml 中取消注释 auth 段:
auth:
  htpasswd:
    realm: "Docker Registry"
    path: /auth/htpasswd
  1. docker-compose.yml private 服务里挂载:
volumes:
  - ./auth:/auth:ro
  1. 重启:docker compose restart private

登录:

docker login localhost:5001
# 输入 teacher / secret123

缓存说明

  • mirror 数据存在 ./data/mirror/,拉过的镜像断网也能用
  • private 数据存在 ./data/private/
  • mirror 的 pull-through cache 不支持 push(Registry 限制)
  • 如需清理缓存:docker compose stop mirror && rm -rf ./data/mirror/* && docker compose start mirror

暴露到局域网(让其他机器也用)

把 daemon.json 里的 localhost 换成服务器 IP:

{
  "registry-mirrors": ["http://192.168.1.100:5000"],
  "insecure-registries": ["192.168.1.100:5000", "192.168.1.100:5001"]
}

⚠️ HTTP 非加密,仅建议内网使用。生产环境建议加 Nginx + TLS。

1 Answers

docker-compose.yml

version: "3.8"

# ============================================================
# 老师的 Docker Hub —— 镜像站 + 私有仓库
# ============================================================
#
# 端口说明:
#   5000  → mirror   拉取时自动代理 Docker Hub(pull-through cache)
#   5001  → private  可以 push 自己的镜像(私有仓库)
#   8080  → ui       Web 界面,查看所有镜像
#
# 用法:
#   拉镜像:docker pull localhost:5000/library/nginx:latest
#   推镜像:docker push localhost:5001/myimage:v1
# ============================================================

services:

  # ----------------------------------------------------------
  # 1. Pull-through 镜像缓存(主角)
  #    没有的镜像 → 去 Docker Hub 取 → 缓存到本地
  # ----------------------------------------------------------
  mirror:
    image: registry:2
    container_name: docker-mirror
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - ./config/registry-mirror.yml:/etc/docker/registry/config.yml:ro
      - ./data/mirror:/var/lib/registry
    environment:
      REGISTRY_LOG_LEVEL: info
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:5000/v2/"]
      interval: 30s
      timeout: 5s
      retries: 3

  # ----------------------------------------------------------
  # 2. 私有仓库(可推送)
  #    docker push localhost:5001/your-image:tag
  # ----------------------------------------------------------
  private:
    image: registry:2
    container_name: docker-private
    restart: unless-stopped
    ports:
      - "5001:5000"
    volumes:
      - ./config/registry-push.yml:/etc/docker/registry/config.yml:ro
      - ./data/private:/var/lib/registry
    environment:
      REGISTRY_LOG_LEVEL: info
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:5000/v2/"]
      interval: 30s
      timeout: 5s
      retries: 3

  # ----------------------------------------------------------
  # 3. Web UI —— 查看镜像列表(可选,注释掉也没关系)
  # ----------------------------------------------------------
  ui:
    image: joxit/docker-registry-ui:latest
    container_name: docker-registry-ui
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      # 指向私有仓库(mirror 是只读 proxy,UI 展示私有仓库更有意义)
      - SINGLE_REGISTRY=true
      - REGISTRY_TITLE=老师的 Docker Hub
      - NGINX_PROXY_PASS_URL=http://private:5000
      - SHOW_CONTENT_DIGEST=true
      - TAGLIST_ORDER=num-asc
      - CATALOG_ELEMENTS_LIMIT=1000
      - DELETE_IMAGES=true
    depends_on:
      - private