在Ubuntu 14.04上设置私有Docker Registry

【Docker系列】6-Docker Hub和Registry实战 官方配置参考 https://docs.docker.com/engine/reference/commandline/dockerd/官方参考 https://docs.docker.com/registry/configuration/指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型; 阅读详情

提供:ZStack云计算

前言

Docker不仅是一个强大的服务器部署工具,而且它还有一个官方的Docker Hub registry用于储存Docker镜像。上传镜像到Docker Hub是免费的,上传的镜像文件同时也对公共领域开放,而这可能不是我们想要的。

本文介绍如何配置一个私有的Docker registry,在此上传的镜像是私密的,你可以从另一个联网的主机以安全的方式下载此registry上的镜像。

本文仅介绍registry的创建,而不讨论应用的容器化。有关Docker镜像创建的操作可参考这篇Docker入门文章。

本文在Ubuntu 14.04上实测通过,在其他Debian类系统上应该也可以通过。使用的Docker Registry版本为2.0版。

Docker基本概念

如果你此前尚未用过Docker,那么最好先花几分钟时间了解一下它的基本概念。如果你已经使用过Docker,只想了解建立私有registry部分的内容,则可跳过本小节。

Docker入门者可参阅这篇Docker Cheat Sheet。

Docker的核心理念是应用及其依赖项与其运行环境(操作系统)的分离,这种分离通过容器(containers)和镜像(images)来实现。一个Docker镜像本质上来说就是一个文件系统的模板,运行一个Docker镜像就是在你的系统上的一个Docker容器中运行该文件系统的一个实例。默认来说,该容器是不会接触到最初的那个镜像或者Docker运行环境所处的宿主机上的文件系统:该容器是完全独立的环境。

在容器内部操作进行的变更直接在容器中预存,而不会造成初始镜像的变更;要保存这些变更,需要通过docker commit指令将变更提交给指定的Docker镜像。也就是说,从一个旧的容器,你可以不断的生成新的容器,而旧的那个容器(镜像)永远也不会因为意外而被搞砸。该模式对于git用户而言应该非常眼熟,这相当于创建新的分支(git branch相当于Docker image),运行一个镜像相当于做一次git checkout。

运用同样的类比,一个私有Docker registry就相当于一个私有的git仓库。

准备工作

完成本教程需要如下准备工作:

  • 两台Ubuntu 14.04的云主机,一台作为私有Docker registry服务器,一台作为Docker客户端。
  • 两台服务器上都建立具有sudo权限的非root用户(用户建立教程可参考这篇文章)。
  • 两台服务器上都安装Docker以及Docker Compose(安装教程见此)。
  • 为私有Docker registry服务器配置好可供客户端访问的域名。

步骤1:安全加固

针对Docker Registry的安全加固,建议使用Docker Compose。如此,我们可以在一个容器内运行Docker Registry,而与外部的通讯安全则交给另一个容器内的Nginx来处理。我们在准备工作中应该已经安装过Docker Compose。

用Nginx来处理通讯安全,则需要将可访问私有registry的用户名和密码的列表保存到一个文件里以供Nginx读取。我们将安装apache2-utils软件包,该软件包下的htpasswd可以很方便的生成一个Nginx可读的密码哈希:

sudo apt-get -y install apache2-utils

步骤2:安装配置Docker Registry

如果你只需要管理一两个Docker容器,那么Docker命令行工具就足够好了。然而,大部分在容器内运行的应用并非是独立运作的,他们需要成组配合才能运行。比如,大部分Web应用都至少需要一个Web服务器用于托管应用代码、一个服务器用于运行PHP/Ruby on Rails等解释脚本语言、一台数据库服务器(如MySQL)。

Docker Compose可以让我们为每一个容器用一个.yml配置文件,该文件不仅可以指定容器的配置项,还可以写入有关该容器如何对外通讯的信息。docker-compose命令行工具可以对应用的各个组件下达指令。

Docker registry本身也是一个由多个组件组成的应用,因此我们将使用Docker Compose对其进行配置管理。

最简单的registry配置就是其存储数据的位置。让我们先来创建一个最基本的Docker Compose YAML文件。

首先,创建一个目录,用于储存本教程将要用到的一些文件:

mkdir ~/docker-registry && cd $_
mkdir data 

在该目录下创建一个docker-compose.yml文件:

nano docker-compose.yml

将如下内容复制粘贴到该文件中:

registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

注意这部分内容:environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data为Docker registry容器设置了一个环境变量路径/data,如此,Docker registry在启动时就会检查这个环境变量,从而将其数据保存到/data路径下。

最后的volumes: - ./data:/data这一段的意思是,容器内的/data路径应该映射到宿主机的./data路径,也就是说Docker registry的数据都会保存到宿主机的~/docker-registry/data目录下。

现在启动Docker Compose:

cd ~/docker-registry
docker-compose up

输入该命令后,你会看到一系列下载进度条,这些是Docker在从官方Registry下载Docker registry镜像文件的下载进度。如果一切顺利,下载应该在一两分钟内完成,最终呈现的输出应该是这样的:

registry_1 | time="2015-10-18T23:45:58Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="redis not configured" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="using inmemory blob descriptor cache" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="listening on [::]:5000" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1
registry_1 | time="2015-10-18T23:45:58Z" level=info msg="Starting upload purge in 1m0s" instance.id=44c828de-c27a-401e-bb2e-38b17e6a4b7b version=v2.1.1

里面有一条No HTTP secret provided的警告信息,不用在意它。

至此,你的Docker registry已经在运行,监听端口为5000(这个端口可以在docker-compose.yml文件中的ports:部分设置)。不过这个registry现在还用处不大:一方面它需要手动启动,另一方面它还没设置任何身份验证机制所以并不安全。

默认状态下,Docker Compose会一直等待你输入指令。现在我们直接CTRL-C将其关闭退出。

步骤3:设置Nginx容器

现在来解决安全认证的问题。首先我们需要一个Nginx容器,再把它跟刚才的Docker registry容器连接起来。

创建一个新目录用于保存Nginx配置项:

mkdir ~/docker-registry/nginx

打开刚才的docker-compose.yml文件:

nano docker-compose.yml

将下面的内容复制粘贴到文件开头处:

nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro

这将基于官方Nginx镜像创建一个新的Docker容器。注意这里的links部分,这个功能可以自动建立两个容器之间的连接:当Nginx容器启动时,它将能够直接使用registry这个主机名访问registry容器(无论该容器的IP地址为何。其背后的机制其实是在nginx容器里面的/etc/hosts文件把registry容器的IP自动填写进去)。

volumes:部分跟上面一样,是容器内外路径的映射关系。末尾的:ro意思是只读,即该Nginx容器对宿主机文件系统只有只读权限。

到目前为止,完整的docker-compose.yml文件应该是这样的:

nginx:
  image: "nginx:1.9"
  ports:
    - 5043:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

现在如果再次运行docker-compose up,将会启动两个容器:一个Docker registry和一个Nginx。不过我们需要先配置好Nginx。创建一个新的Nginx配置文件registry.conf:

nano ~/docker-registry/nginx/registry.conf

将如下内容复制粘贴进去:

upstream docker-registry {
  server registry:5000;
}

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

  # disable any limits to avoid HTTP 413 for large image uploads
  client_max_body_size 0;

  # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
  chunked_transfer_encoding on;

  location /v2/ {
    # Do not allow connections from docker 1.5 and earlier
    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
    if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
      return 404;
    }

    # To add basic authentication to v2 use auth_basic setting plus add_header
    # auth_basic "registry.localhost";
    # auth_basic_user_file /etc/nginx/conf.d/registry.password;
    # add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;   # required for docker client's sake
    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

保存退出。现在可以启动Docker Compose了:

docker-compose up

Nginx在启动时没有输出信息,不过我们可以用curl来测试一下它是不是已经成功启动并连接至registry。首先用curl发送HTTP请求给registry:

curl http://localhost:5000/v2/

你应该能看到返回的结果——一个空json对象:

{}

现在再给Nginx端口发送HTTP请求:

curl http://localhost:5043/v2/

你应该看到同样的返回结果:

{}

如果一切顺利,在docker-compose的终端能看到如下的输出内容:

    registry_1 | time="2015-08-11T10:24:53.746529894Z" level=debug msg="authorizing request" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
    registry_1 | time="2015-08-11T10:24:53.747650205Z" level=info msg="response completed" environment=development http.request.host="localhost:5043" http.request.id=55c3e2a6-4f34-4b0b-bc57-11c814b4f4d3 http.request.method=GET http.request.remoteaddr=172.17.42.1 http.request.uri="/v2/" http.request.useragent="curl/7.35.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=8.143193ms http.response.status=200 http.response.written=2 instance.id=55634dfc-c9e0-4ec9-9872-6f4930c17759 service=registry version=v2.0.1
    registry_1 | 172.17.0.21 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.35.0"
    nginx_1    | 172.17.42.1 - - [11/Aug/2015:10:24:53 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.35.0" "-"

如果你看到registry_这样的前缀(后面的数字不一定是1),则说明一切正常,Nginx已经成功建立了到Docker registry的代理。

CTRL-C退出,准备进行下一步操作。

步骤4:设置验证信息

现在我们需要让Nginx验证访问Docker registry的用户权限。首先我们需要用htpasswd工具创建一个Apache格式的验证文件(Nginx也可以识别该文件):

cd ~/docker-registry/nginx
htpasswd -c registry.password USERNAME

其中的USERNAME是你自己指定的用户名。指令输入后,命令行会请求为该用户建立一个密码。

如果以后要添加新用户,还是一样使用htpasswd工具,只是不用再输入-c选项了(c是新建的意思):

htpasswd registry.password USERNAME

现在我们有了一个registry.password文件,里面保存了可以访问registry的用户名列表。这个文件是可以随时查看编辑的。

接下来需要让Nginx把这个文件用起来。还是打开~/docker-registry/nginx/registry.conf文件:

nano ~/docker-registry/nginx/registry.conf

找到下面这几行内容:

# To add basic authentication to v2 use auth_basic setting plus add_header
# auth_basic "registry.localhost";
# auth_basic_user_file /etc/nginx/conf.d/registry.password;
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

将auth_basic和add_header这两行前面的井号去掉:

# To add basic authentication to v2 use auth_basic setting plus add_header
auth_basic "registry.localhost";
auth_basic_user_file /etc/nginx/conf.d/registry.password;
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;

这样就启动了HTTP验证功能。保存退出,来把容器们启动起来看看:

cd ~/docker-registry
docker-compose up

还是用curl来给Nginx发送请求:

curl http://localhost:5043/v2/

这次的返回结果是一个验证失败的页面:

<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.9.7</center>
</body>
</html>

现在加上用户名和密码,再用curl发送一次请求:

curl http://USERNAME:PASSWORD@localhost:5043/v2/

这次,你应该能看到之前的返回结果——空json对象{}。在docker-compose的终端也能够看到registry_部分的内容。

CTRL-C退出,准备进行下一步。

步骤5:设置SSL

虽然已经有了基本的HTTP验证,但现在还是不够安全,因为连接是未加密的。我们需要把SSL启用起来。还是打开刚才的Nginx配置文件:

nano ~/docker-registry/nginx/registry.conf

找到如下内容:

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  # ssl on;
  # ssl_certificate /etc/nginx/conf.d/domain.crt;
  # ssl_certificate_key /etc/nginx/conf.d/domain.key;

把SSL以下的三行前面的井号删掉。不要忘了把server_name部分的值改成你的服务器域名:

server {
  listen 443;
  server_name myregistrydomain.com;

  # SSL
  ssl on;
  ssl_certificate /etc/nginx/conf.d/domain.crt;
  ssl_certificate_key /etc/nginx/conf.d/domain.key;

保存退出。Nginx将使用/etc/nginx/conf.d/domain.crt证书以及/etc/nginx/conf.d/domain.key密钥来提供SSL服务。根据之前的配置,容器内的/etc/nginx/conf.d/路径是映射到宿主机的~/docker-registry/nginx/路径下,所以我们需要把证书文件复制到这里。你可以购买证书,也可以获取一个免费的SSL证书。或者,你也可以使用自签名的SSL证书。

自签名的SSL证书

目前为止,Docker还无法正式支持自签名的SSL证书,所以这个配置起来要麻烦一些——我们需要将宿主机设置为证书的颁发机构。

到~/docker-registry/nginx目录下,创建一个新的root key:

cd ~/docker-registry/nginx
openssl genrsa -out devdockerCA.key 2048

生成一个root证书(需要填写国家省市信息之类的,这些可以随便填):

openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt

然后,生成key(这个密钥就是上面需要用到的ssl_certificate_key):

openssl genrsa -out domain.key 2048

然后,我们需要进行一个证书签名的请求。

输入如下命令。输入之后,OpenSSL会向你提出几个问题。其他问题怎么回答都好,不过关于"Common Name"这一项,务必要填写服务器的域名或IP:

openssl req -new -key domain.key -out dev-docker-registry.com.csr

比如,如果你的Docker registry使用的域名是www.ilovedocker.com,则需要这样填写:

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.ilovedocker.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

A challenge password []:这里不要填。

然后,我们要给这个证书请求做签名:

openssl x509 -req -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -out domain.crt -days 10000

因为我们刚才生成的这些证书没有被任何权威机构(比如VeriSign)验证过,因此我们需要用另外的方法告诉所有使用这个Docker registry的客户端说,这个Docker registry使用的证书是合法的。这个方法就是,在每个Docker客户端上做如下设置(需要把刚才生成的devdockerCA.crt复制过去):

sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert
sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert
sudo update-ca-certificates

重启Docker守护进程以使该证书生效:

sudo service docker restart

详细配置过程见本文步骤9。上述指令在本机执行可直接生效。

步骤6:测试SSL

现在启动容器:

cd ~/docker-registry
docker-compose up

再做一次curl,但是用https(这里输入的域名或IP必须与刚才在证书生成过程中填写的Common Name部分完全一致):

curl https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

如果刚才用了自签名证书,你会看到如下问题报告:

curl: (60) SSL certificate problem: self signed certificate

为curl命令加上-k选项可以跳过该验证:

curl -k https://USERNAME:PASSWORD@[YOUR-DOMAIN]:5043/v2/

如此,应该可以得到空json对象{}的返回结果。docker-compose的终端窗口那边也会输出registry_部分内容。否则的话,则需要回去重新检查SSL设置的步骤。

至此,如果你的防火墙配置允许来自外部的请求访问5043端口,则你应该可以使用自己的用户名和密码通过docker login https://<YOURDOMAIN>登陆到该Docker registry上了。

步骤7:将SSL端口设置为443

443是标准的SSL端口,所以我们要把之前设置的5043改成443。不过在Linux上,1024以下的端口都是“特权”端口,所以docker-compose容器必须以root权限运行才能使用该端口。

打开docker-compose.yml进行编辑:

nano ~/docker-registry/docker-compose.yml

在Nginx部分的ports:段落,原本的内容是- 5043:443,即把宿主机的5043端口映射到Nginx容器的443端口。我们要把它改成- 443:443:

nginx:
  image: "nginx:1.9"
  ports:
    - 443:443
  links:
    - registry:registry
  volumes:
    - ./nginx/:/etc/nginx/conf.d:ro
registry:
  image: registry:2
  ports:
    - 127.0.0.1:5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data

CTRL-C退出之前运行的docker-compose(如果之前已经退出就无需进行此操作),然后以sudo权限再次启动:

sudo docker-compose up

现在docker-compose已经启动,再次使用curl命令来做一次测试。这次我们在URL中不再指定端口:

curl https://<YOURUSERNAME>:<YOURPASSWORD>@YOUR-DOMAIN/v2/

检查返回的结果是否为{},docker-compose终端窗口的输出是否包含registry_。在外部的另一台机器上重复本操作,以确保Docker registry可以从外部访问。

如果一切正常,CTRL-C退出,准备进行下一步。

步骤8:将Docker Registry启动为服务

接下来我们创建一个Upstart脚本以使Docker registry在每次系统启动时一起启动。

首先我们需要移除之前已经生成的容器,好把整个Docker registry目录移动到系统通用目录下,再将其权限更改为root权限:

cd ~/docker-registry
docker-compose rm   # 移除现有的容器 
sudo mv ~/docker-registry /docker-registry
sudo chown -R root: /docker-registry

然后创建一个Upstart脚本:

sudo nano /etc/init/docker-registry.conf

将以下内容复制粘贴到文件中(该脚本内容有一些复杂,其说明可参考这篇博文。有关Upstart的用法可参考这篇教程。):

description "Docker Registry"

start on runlevel [2345]
stop on runlevel [016]

respawn
respawn limit 10 5

chdir /docker-registry

exec /usr/local/bin/docker-compose up

现在用如下命令测试一下该Upstart脚本:

sudo service docker-registry start

返回的结果应该是这样的:

docker-registry start/running, process 25303

使用如下命令检查Docker服务是否已经在运行:

docker ps

返回的结果应该是这样的(其中包含dockerregistry_的项目):

CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                          NAMES
d4b6fef0b4d1        nginx:1.9           "nginx -g 'daemon of   2 minutes ago       Up 2 minutes        80/tcp, 0.0.0.0:443->443/tcp   dockerregistry_nginx_1
77668352bd39        registry:2          "registry cmd/regist   2 minutes ago       Up 2 minutes        127.0.0.1:5000->5000/tcp       dockerregistry_registry_1

Upstart会把docker-compose命令的输出都录入到/var/log/upstart/docker-registry.log日志文件中。用tail命令检查一下这个日志文件(需要使用sudo,因为upstart日志是以root用户写入的):

sudo tail -f /var/log/upstart/docker-registry.log

里面应该能看到包含registry_的条目。再从本机的新终端窗口或另一台机器curl到registry服务器上:

curl https://<YOUR_USERNAME>:<YOURPASSWORD>@[YOUR-DOMAIN]/v2/

检查返回的结果是否为{}。日志文件中应该能看到跟之前一样的信息:

registry_1 | time="2015-08-12T08:01:12.241887501Z" level=debug msg="authorizing request" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | time="2015-08-12T08:01:12.242206499Z" level=info msg="response completed" environment=development http.request.host=docker.meatflavoredbeer.com http.request.id=e8d69e16-9448-4c48-afd8-57b1f1302742 http.request.method=GET http.request.remoteaddr=106.1.247.4 http.request.uri="/v2/" http.request.useragent="curl/7.37.1" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.359883ms http.response.status=200 http.response.written=2 instance.id=14d4727b-fda1-463f-8d0e-181f4c70cb17 service=registry version=v2.0.1
registry_1 | 172.17.0.4 - - [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "curl/7.37.1"
nginx_1    | 106.1.247.4 - nik [12/Aug/2015:08:01:12 +0000] "GET /v2/ HTTP/1.1" 200 2 "-" "curl/7.37.1" "-"

步骤9:配置需要访问Docker Registry的客户端

如步骤5所述,对于使用自签名SSL证书的情况,所有需要访问该Docker registry的客户端都需要添加我们创建的证书。我们需要把~/docker-registry/nginx/devdockerCA.crt这个文件复制到客户端机器上。

首先在服务器上查看该证书文件:

sudo cat /docker-registry/nginx/devdockerCA.crt

文件内容差不多是这样的形式:

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJANiXy7fHSPrmMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwOTIxMDYwODE2WhcNNDIwMjA2MDYwODE2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuK4kNFaY3k/0RdKRK1XLj9+IrpR7WW5lrNaFB0OIiItHV9FjyuSWK2mj
ObR1IWJNrVSqWvfZ/CLGay6Lp9DJvBbpT68dhuS5xbVw3bs3ghB24TntDYhHMAc8
GWor/ZQTzjccHUd1SJxt5mGXalNHUharkLd8mv4fAb7Mh/7AFP32W4X+scPE2bVH
OJ1qH8ACo7pSVl1Ohcri6sMp01GoELyykpXu5azhuCnfXLRyuOvQb7llV5WyKhq+
SjcE3c2C+hCCC5g6IzRcMEg336Ktn5su+kK6c0hoD0PR/W0PtwgH4XlNdpVFqMST
vthEG+Hv6xVGGH+nTszN7F9ugVMxewIDAQABo1AwTjAdBgNVHQ4EFgQULek+WVyK
dJk3JIHoI4iVi0FPtdwwHwYDVR0jBBgwFoAULek+WVyKdJk3JIHoI4iVi0FPtdww
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkignESZcgr4dBmVZqDwh
YsrKeWSkj+5p9eW5hCHJ5Eg2X8oGTgItuLaLfyFWPS3MYWWMzggxgKMOQM+9o3+k
oH5sUmraNzI3TmAtkqd/8isXzBUV661BbSV0obAgF/ul5v3Tl5uBbCXObC+NUikM
O0C3fDmmeK799AM/hP5CTDehNaFXABGoVRMSlGYe8hZqap/Jm6AaKThV4g6n4F7M
u5wYtI9YDMsxeVW6OP9ZfvpGZW/n/88MSFjMlBjFfFsorfRd6P5WADhdfA6CBECG
LP83r7/MhqO06EOpsv4n2CJ3yoyqIr1L1+6C7Erl2em/jfOb/24y63dj/ATytt2H
6g==
-----END CERTIFICATE-----

把证书内容复制到剪贴板上。

登陆到客户端机器,创建证书目录:

sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert

再创建证书文件,使用同样的文件名devdockerCA.crt:

sudo nano /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

将刚才复制到剪贴板上的内容粘贴进来。保存退出。再使用cat查看一下新创建的文件,检查内容是否正确:

cat /usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt

确认无误后,更新证书信息:

sudo update-ca-certificates

返回的结果应该包含1 added信息:

Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.

重启Docker以重新加载系统CA证书列表:

sudo service docker restart

现在可以使用如下指令登入Docker registry了:

docker login https://YOUR-DOMAIN

服务器会要求你输入用户名、密码和Email。用户名和密码就是刚才在服务器上创建的,Email可以随便填:

Username: USERNAME
Password: PASSWORD
Email: 
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

如果输入的信息无误,应该可以看到登陆成功的信息:

Login Succeeded

步骤10:将本机镜像发布到Docker Registry

我们先在客户端上创建一个简单的镜像(基于Docker Hub上的ubuntu镜像。如果本机上已经有镜像那就可以省去这一步了):

docker run -t -i ubuntu /bin/bash

该指令会下载ubuntu镜像并运行其中的bash以等待我们给该容器输入指令,这可能需要一段时间。等等待输入的指令出现之后,我们来创建一个文件SUCCESS:

touch /SUCCESS

现在可以退出容器了:

exit

将变更后的镜像提交为test-image:

docker commit $(docker ps -lq) test-image

根据我们上面的操作,这个test-image镜像与官方ubuntu镜像相比,只是添加了一个空文件SUCCESS。

现在我们把这个测试镜像推送到registry。

登陆到registry服务器:

docker login https://YOUR-DOMAIN

输入用户名和密码:

Username: USERNAME
Password: PASSWORD
Email: 
Account created. Please see the documentation of the registry http://localhost:5000/v1/ for instructions how to activate it.

现在可以推送刚才的镜像。根据Docker的设计,我们推送之前,需要给它加一个tag用于标注registry的位置:

docker tag test-image [YOUR-DOMAIN]/test-image

这里需要注意的是,tag中的域名不需要https://,只需要域名、端口、加上镜像名称即可。

现在可以推送了:

docker push [YOUR-DOMAIN]/test-image

推送需要一段时间,完成后应该能看到如下内容:

latest: digest: sha256:5ea1cfb425544011a3198757f9c6b283fa209a928caabe56063f85f3402363b4 size: 8008

步骤11:从Docker Registry拉取镜像

现在测试从另一台机器拉取该镜像(我们也可以直接在registry服务器上进行本测试)。

登陆到registry服务器:

docker login https://[YOUR-DOMAIN]

使用刚才创建的tag拉取镜像:

docker pull [YOUR-DOMAIN]/test-image

Docker会下载该镜像。下载完成后,输入如下指令运行镜像以进入到里面:

docker run -t -i [YOUR-DOMAIN]/test-image /bin/bash

看看里面是不是有刚才创建的文件:

ls

应该可以看到SUCCESS文件出现在列表中:

SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

总结

至此,我们已经成功创建了一个私有Docker Registry服务器,并且完成了镜像的推送和拉取。现在可以尽情的玩弄你的Docker啦!

本文来源自DigitalOcean Community。英文原文:How To Set Up a Private Docker Registry on Ubuntu 14.04

翻译:lazycai

在ubuntu14.04上构建docker私有镜像库 构建docker私有镜像库环境准备Docker私有镜像库,分为服务端和客户端。服务端和客户端都要有docker环境。除此之外,服务端运行registry容器,完成镜像库的功能。客户端通过docekr pull、push等命令与服务端交互。环境说明如下表: 对象 版本 IP 备注 服务端 Ubuntu 14.04 192.168.142.128 在此主机上搭建镜像库 阅读详情

相关推荐

Ubuntu 18.04 私有 Docker Registry 生产级部署指南

私有 Docker Registry 是容器化生产环境的核心基础设施,其本质是解决镜像分发的确定性、安全性和可审计性问题。基于 Docker 镜像仓库原理,它通过内容寻址(digest)、分层存储与元数据管理保障镜像一致性;技术价值在于规避公共仓库变更风险、实现细粒度访问控制与内网高效分发。典型应用场景包括金融/制造等强合规行业在 Ubuntu LTS 系统上的 CI/CD 流水线、多团队协作开发及离线环境交付。本文聚焦 Ubuntu 18.04 这一广泛使用的长期支持版本,结合 registry:2 镜像

weixin_30684743的博客 364

从Docker容器安装Registry时遇到的问题

1、构建时出错:(命令和输出如下)[root@ct ~]# docker run -p 5000:5000 registry:2Unable to find image 'registry:2' locally2: Pulling from library/registry81033e7c1d6a: Pull completeb235084c2315: Pull completec692f3a68...

linkvivi的博客 3723

Ubuntu 18.04 搭建高可用私有 Docker Registry 实战

Docker Registry 是容器镜像分发的核心基础设施,其本质是遵循 HTTP API v2 规范的元数据与 Blob 存储服务。在企业级生产环境中,私有 Registry 不仅需解决基础镜像托管问题,更承担着认证鉴权、TLS 加密、访问审计、生命周期管控等关键职责。相比公共仓库,私有化部署可规避速率限制、镜像覆盖风险及网络策略依赖,尤其适配金融、政务等强合规场景。Ubuntu 18.04 因其长期支持(LTS)、overlay2 存储驱动成熟、systemd 稳定性及与 Docker CE 19.0

342

Docker搭建私有仓库

默认情况下,在执行docker pull命名时,docker是从官方的镜像源地址拉取下载镜像的,即registry.hub.docker.com这个地址。该地址是docker公司提供的公共仓库。 对于具有商业秘密的项目上传到官方的公共仓库是不安全的,如果在单位内部需要统一管理并共享单位内部使用的镜像,需要搭建私有仓库。 所谓的私有仓库,就是在本地(局域网)搭建类似公共仓库的镜像仓库,可以将镜像提交...

Jamza的博客 579

Ubuntu 18.04 搭建生产级私有 Docker Registry 实战

私有 Docker Registry 是容器化基础设施中实现镜像安全存储与可控分发的核心组件,其本质是一个遵循 Docker Registry HTTP API v2 协议的轻量级存储服务。它通过文件系统或对象存储持久化镜像层(blob)与清单(manifest),依赖 TLS 加密、HTTP 基础认证及反向代理实现传输安全与访问控制。相比公有仓库,私有 Registry 显著提升内网拉取效率、规避速率限制,并满足等保、GDPR 等对敏感镜像(如含配置/脱敏数据的 Spring Boot 或 Python

weixin_33997389的博客 405

TC3xx系列LMU与SPR实战:将关键算法从Flash搬移至PSPR提升5倍执行效率

在实际电机控制项目中,通过将FOC算法全部迁移到PSPR,我们不仅将执行时间从56μs降至11μs,还将最坏情况下的时间偏差控制在±0.3μs以内。实测数据:在TC397上执行Flash中的32位浮点矩阵乘法,平均每条指令需要8.7个周期,而同样的代码在PSPR中仅需1.2个周期。传统开发中,工程师往往将所有代码放在Flash中运行,这相当于让F1赛车在乡村公路上行驶。迁移后不仅平均执行时间缩短,更重要的是时间抖动从±15%降低到±2%以内,这对闭环控制系统至关重要。不是所有代码都适合迁移到PSPR。

weixin_31421613的博客 299

Docker学习七:网络基础

docker网络基础

VacantYang的博客 383

具身智能落地实战:制造业、物流与电力的工业级方案设计

具身智能是一种融合感知、推理与物理执行的智能范式,其核心在于构建具备因果建模能力、多模态闭环反馈和实时动作规划的行动主体。区别于通用AI或传统自动化,它依托多模态大模型、高精度力觉/触觉传感及Sim2Real仿真技术,实现对真实物理环境的深度理解与自适应交互。技术价值体现在可解释性决策、毫秒级跨模态协同与零停机容错能力,已规模化应用于制造业质检、物流破损鉴定、电力绝缘子巡检等强约束工业场景。本文聚焦‘行业应用方案解决方案’这一高频搜索需求,系统拆解从工位筛选、分层架构设计到72小时现场交付的全链路工程方法论

weixin_30952479的博客 304

ubuntu 22.04 配置docker registry

【代码】ubuntu 22.04 配置docker registry。

qq_36481693的博客 724

电源设计避坑指南:半桥LLC软启动的5个常见错误及解决方案

本文针对半桥LLC谐振变换器软启动过程中的五个常见设计错误,提供了详细的工程解决方案。重点分析了忽视谐振腔初始状态导致的电流冲击、软启动斜坡与环路带宽不匹配、开环到闭环切换时机不当、变压器偏磁以及参数未考虑边界条件等问题,并给出了包括主动预充电、自适应斜坡、最佳切换点判定等实用调试技巧,帮助工程师实现平稳可靠的电源启动。

weixin_29260291的博客 284

【Unity】Unity性能分析解决方案——UPR

由Unity中国团队提供的一套性能优化解决方案,其是一系列性能工具的集合,并可将收集的数据进行可视化。

Davidorzs的博客 1009

Ubuntu14.04安装Docker及构建私有仓库

在Ubuntu14.04上安装Docker 配置Docker的安装源 sudo apt-get update sudo apt-get install apt-transport-https sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A

何松林的专栏 3080

AUTOSAR AP平台开发避坑指南:基于华为MDC的接口配置与数据通道实战

本文详细解析了AUTOSAR AP平台与华为MDC的协同开发实践,涵盖接口配置、数据通道优化及资源分配策略。通过实战案例展示如何解决传感器接入、通信协议栈优化等常见问题,提升智能驾驶系统性能。特别针对MDC平台特性,提供执行管理、调试调优及安全设计的专业指导,助力开发者高效完成ADAS/AD系统开发。

julia4scientist的博客 1140

搭建私有Docker Registry

Registry是Docker的重要组件--镜像仓库, 与OpenStack的Glance有一些相似之处。 我们可以使用Docker官方的Registry,但是可能会受到网络的影响,那么我们在本地搭建自己的私有Registry! 下面是我在Ubuntu 14.04上搭建Docker Registry的具体过程: 1.   docker-registry是使用Python来开发的,我们会使用p

疯哥哥带你飞 483

基于YOLOv8的人群聚集检测系统:含UI界面设计与数据集应用

人群聚集检测是智慧城市、公共安全和疫情防控等领域的重要任务。本文结合YOLOv8最新目标检测技术,设计并实现了一个高效的人群聚集检测系统,支持可视化UI界面操作,方便用户实时检测和分析视频中的人群密度。本文详细介绍了系统设计思路、使用的数据集、YOLOv8模型训练和推理过程,以及UI界面的开发与整合。最后通过实验验证了该系统的实用性和性能表现。更灵活的模型架构强化的特征融合网络(PAN++)自动混合精度训练支持支持多任务学习(目标检测+分类+分割)预训练模型丰富,适应多种应用场景。

YOLO 434

【算法】克里金kriging参数值预测模型

模型中特征值2个,目标值1个,data数据集如图所示。搭建kriging参数值预测模型。

weixin_48618536的博客 5060

搭建nginx+registry的private registry

一、环境 1. ubuntu 14.04虚拟机两台,虚拟的IP是192.168.110.138和192.168.110.137 2. docker 1.12.0 3.192.168.110.138的hostname配置成ip-192-168-138-.ec2.internal 4.在192.168.110.138和192.168.110.137的hosts文件中分别添加如下内容: 192

xuguokun1986的博客 669

LeRobot 入门教程(一)软件环境、部署流程及摄像头配置

🤖 LeRobot:开源机器人学习平台 摘要:LeRobot是一个基于PyTorch的开源机器人学习平台,提供模型、数据集和工具,旨在降低机器人技术门槛。平台包含经过验证的模仿学习和强化学习方法,并提供预训练模型、人类演示数据集及模拟环境。安装需从源码获取,支持Python 3.10环境,可选扩展包括仿真环境(如gym-aloha)、电机控制(Dynamixel/Feetech SDK)和实验跟踪(Weights & Biases)。该平台托管在HuggingFace,并设有社区Discord频道

2506_90492529的博客 3418

Docker学习笔记六:Docker搭建企业级私有仓库

前言Docker不仅是一个强大的服务器部署工具,而且它还有一个官方的Docker Hub registry用于储存Docker镜像。上传镜像到Docker Hub是免费的,上传的镜像文件同时也对公共领域开放,而这可能不是我们想要的。本文介绍如何配置一个私有的Docker registry,在此上传的镜像是私密的,你可以从另一个联网的主机以安全的方式下载此registry上的镜像。本文仅介绍regi...

weixin_33989780的博客 438

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

搭建docker私有仓库

最近公司所用的采集器想要全部换成docker来搭建,所以要自己搭建个docker的私有仓库,由此记录下搭建过程。 所用到的系统主要又ubunut14.04和centos7.3,他们的配置有所不同 主机1内网 IP:192.168.10.160 (仓库) 主机2内网 IP:192.168.10.161 主机3内网 IP:192.168.10.163 第一步:安装docker ubuntu...

weixin_30906185的博客 147

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

docker 制作本地镜像_Docker搭建自己的本地镜像仓库的步骤

一、环境以及准备工作1.ubuntu14.042.docker环境二、搭建过程1.更换镜像源(因为默认的太慢了,国内的更快)sudo vim /etc/default/docker输入以下参数:DOCKER_OPTS="--registry-mirror=http://hub-mirror.c.163.com" //网易的,也可以使用daoClouds的如果是刚安装的ubuntu环境的话,执行以下...

weixin_39838302的博客 1311

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

docker学习之搭建自己的本地镜像仓库

一、环境以及准备工作1.ubuntu14.042.docker环境二、搭建过程1.更换镜像源(因为默认的太慢了,国内的更快)sudo vim /etc/default/docker 输入以下参数: DOCKER_OPTS="--registry-mirror=http://hub-mirror.c.163.com" //网易的,也可以使用daoClouds的 如果是刚安装的ubuntu环境的话,执...

汪康的博客 4万+

如何在Ubuntu14.04上搭建私有docker registry

本文详细介绍了如何搭建私有docker registry的过程。并在registry前面架设Nginx通过ssl实现权限认证和加密。

czw8528的专栏 1752

Ubuntu 18.04 下 Docker 私有镜像仓库生产级部署指南

Docker 私有镜像仓库是微服务与 DevOps 实践中的核心基础设施,其本质是基于 HTTP v2 协议的容器镜像存储与分发服务。它通过 Registry 服务实现镜像层(layer)的上传、拉取与元数据管理,依赖 HTTPS 加密通信、身份认证(如 basic auth 或 LDAP)及持久化存储保障安全与可靠性。技术价值在于解决公有仓库限速、密钥泄露、网络不可控等生产痛点,支撑 CI/CD 流水线稳定运行。典型应用场景包括企业内网镜像分发、边缘计算节点部署、AI 模型服务版本管控及合规审计需求。本文

weixin_30740295的博客 456

[Docker] ubuntu14.04LTS 上部署自己的 provider docker registry

在调研 Marathon  的过程中遇到了一个问题。就是每次新建APP的时候。总是会重新的去docker hub上push 镜像。导致每次启动app的时间都很漫长,严重影响了自己的进度。而没有找到合适的方式如何让其使用本地的 image, 所以就想就此机会搭建一个自己的 Provider docker registry。 毕竟自己也经常性的需要在不同的机器上部署docker。这样反而提升了部署效率

zhangzhenhao的专栏 487

搭建一个docker registry

  创建docker registry 的流程 简介 安装运行 docker-registry 在私有仓库上传 注意事项 Ubuntu 14.04, Debian 7 Wheezy Ubuntu 16.04+, Debian 8+, centos 7 正确上传 查看仓库中包含镜像 简介 有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓...

吴晓斌的博客 1万+
上一篇: 生产环境构建指南:Web应用——集中式日志记录
下一篇: 如何在CoreOS集群上创建并运行服务
普通网友
博客等级 码龄10年 769粉丝 269原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值