MENU

在树莓派上搭建Docker私有仓库

• May 4, 2020 • Deployment阅读设置

背景

  由于天气开始变暖,放在卧室的服务器产热严重,能将平均室温拉升近十度,直接使得体感温度从舒适到炎热,故而关闭服务器,开始将服务从服务器上迁移到树莓派和个人电脑上。
  接下来很长一段时间,服务器应该只有在需要额外算力时才会开启,但是又不能保证今后不会重新将服务迁移到服务器或者别的地方,所以开始将服务部署在Docker上以方便迁移部署。
  既然要用Docker,相应的也需要有一个私有的Docker仓库,于是开始着手在树莓派上部署Docker仓库。

步骤

一、 在树莓派上安装 Docker

  安装Docker通常只需要一句命令就可以了,如果访问docker.com太慢的话,可以尝试挂个代理

sudo curl -sSL https://get.docker.com | sh

  安装完成后,可以运行hello world来判断是否安装成功

docker run hello-world

二、 拉取registry-arm

  registry是Docker官方提供的用来管理Docker镜像的镜像注册中心,为了能够在树莓派上部署,我们需要拉取arm版的registry

docker pull budry/registry-arm

三、 启动容器

docker run -d -p 5000:5000 --restart always --name registry -v /exta/registry:/var/lib/registry budry/registry-arm

四、 判断是否启动成功

  在浏览器中访问 http://{ip}:5000/v2/_catalog,应该能够打印如下json字符串

{"repositories":[]}

五、 配置HTTPS

  Docker默认是采用HTTPS通信的,如果想要直接采用HTTP,还需要修改客户端的配置,故而为了方便使用,也为了通信安全,需要为registry端配置HTTPS访问支持。
  根据Docker官方文档: Deploy a registry server,我们可以通过在启动registry镜像时指定证书文件,来提供HTTPS支持,由于局域网内还计划搭建其它服务,接下来将不依照官网步骤,而是尝试通过将nginx配置成反向代理来提供HTTPS支持。
  首先在registry服务器上通过openssl自签一个永久证书

mkdir /cert
cd /cert
openssl genrsa -out privkey.pem 2048
openssl req -new -key privkey.pem -out cert.csr
openssl x509 -req -days 36135 -in cert.csr -signkey privkey.pem -out fullchain.pem

  在树莓派上搭建nginx,并用如下配置将443端口的流量转至5000端口

server {
    listen 80;
    server_name docker.sailark.com;
    rewrite ^(.*) https://$host$1 permanent;
}                                                    

server {
    listen 443 ssl;
    server_name docker.sailark.com;
    access_log /var/log/nginx/https_docker.log;

    ssl on;
    ssl_certificate /cert/fullchain.pem;             
    ssl_certificate_key /cert/privkey.pem;           

    client_max_body_size 0;                          

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_read_timeout 30;
        proxy_connect_timeout 30;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

  此时如果将docker.sailark.com通过ddns与路由器的端口转发指向树莓派,那么将可以通过 https://docker.sailark.com/v2/_catalog 读取到json字符串,但是此时的https证书是不被信任的自签证书,为了用上letsencrypt的免费证书,同时也为了公网访问的稳定,需要在公网的服务器上搭建nginx,采用letsencrypt证书,并将流量转发至树莓派的443端口,这样对于外人来讲使用的是leltsencrypt的证书,而对于别有用心的中间人攻击者,公网至树莓派的流量也会被自签证书加密,保证信息安全。

六、 为Docker指定私有仓库

  私有仓库创建好后,接下来就是配置Docker客户端,将私有仓库的地址添加进去,步骤如下

  1. 右键 Docker Desktop 托盘图标
  2. 打开 Settings
  3. 点击 Docker Engine 选项卡
  4. 在registry-mirrors加上私有仓库地址,如果是http的应该加在insecure-registries
  5. 重启 Docker Desktop
{
  "registry-mirrors": [
    "https://docker.sailark.com"
  ],
  "insecure-registries": [],
  "debug": true,
  "experimental": false
}

七、 将Docker镜像传到私有仓库

  首先拉取官方仓库hello-world镜像并运行,可以看到

C:\Users\Nukami
λ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:093df2ad7845fff954aba49fed9c63ed09bfe280706cd849402aab9314982437
Status: Image is up to date for hello-world:latest
docker.io/library/hello-world:latest

C:\Users\Nukami
λ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (windows-amd64, nanoserver-1809)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run a Windows Server container with:
 PS C:\> docker run -it mcr.microsoft.com/windows/servercore powershell

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

  接着用docker images命令,查看本地镜像列表

C:\Users\Nukami
λ docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
hello-world                              latest              c7f4e41fba3a        2 weeks ago         251MB

  用docker tag命令将源镜像与目标镜像绑定,即将私有仓库上的镜像地址与本地镜像的ID绑定,如果仓库上镜像地址不存在,会自动创建。

C:\Users\Nukami
λ docker tag c7 docker.sailark.com/library/hello-world

C:\Users\Nukami
λ docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
hello-world                              latest              c7f4e41fba3a        2 weeks ago         251MB
docker.sailark.com/library/hello-world   latest              c7f4e41fba3a        2 weeks ago         251MB

  将镜像push到私有仓库

C:\Users\Nukami
λ docker push docker.sailark.com/library/hello-world
The push refers to repository [docker.sailark.com/library/hello-world]
e89f7df02616: Layer already exists
2b6dc8c05bdb: Layer already exists
3492c6ad7ce2: Skipped foreign layer
latest: digest: sha256:093df2ad7845fff954aba49fed9c63ed09bfe280706cd849402aab9314982437 size: 1124

  访问 https://docker.sailark.com/v2/_catalog ,可以看到hello-world已经被推到了私有仓库上

{"repositories":["library/hello-world"]}

八、 私有仓库的鉴权

  通过上述步骤,我们成功搭建了一个无需密码即可使用的Docker私有仓库,它虽然方便了我们在不同主机间交换Docker镜像,但也将我们的镜像暴漏于互联网上,这可能成为一些重要环境配置的致命泄漏源。为了让私有仓库不被所有人访问,我们需要为它添加鉴权功能,阻止无权访客的访问。
  首先需要创建目录用来保存登录凭证,比如/auth,然后利用registry创建登录凭证信息。

mkdir /auth
docker run --entrypoint htpasswd budry/registry-arm -Bbn [user] [password] > /auth/htpasswd

  使用新的参数来启动registry

docker run -d -p 5000:5000 --restart always --name registry -v /exta/registry:/var/lib/registry -v `pwd`/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTR Y_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd budry/registry-arm

  这个时候再访问 https://docker.sailark.com/v2/_catalog ,可以看到浏览器会提示你输入用户名密码。
  而在命令行操作Docker访问私有仓库时,需要先通过 docker login docker.sailark.com 进行登录,否则会提示请求不被信任。

总结

  关掉服务器的第二天,连开空调的想法都没了。
  这告诉我们如果有新需求不想解决,也许可以试着解决提出需求的人。

Leave a Comment

已有 1 条评论
  1. 伊丽莎白女王陛下 伊丽莎白女王陛下

    解决提出需求的人Σ(゚∀゚ノ)ノ不要想不开啊帅哥!@(惊哭)