使用SSL验证和Nginx做代理搭建生产环境的Docker仓库

来源:互联网 发布:淘宝冰淇淋机 编辑:程序博客网 时间:2024/05/07 03:48

使用SSL验证和Nginx做代理搭建生产环境的Docker仓库

  使用私有仓库有许多优点:
  节省网络带宽,针对于每个镜像不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可;提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用。
  我的环境:CentOS-7-x86_64-Everything-1511
  Docker版本:Version: 1.10.3,API version: 1.22,Go version: go1.5.3
在下载Linux发行版的时候需要下载较新的版本,Docker所支持的Linux kernel版本过低会出现问题。
一、安装Docker
  CentOS中更新源后安装docker
  官网https://docs.docker.com/engine/installation/linux/centos/
  安装完成Docker环境之后不要去关闭CentOS的防火墙和Selinux,因为Docker的安全机制是基于iptables的,关闭selinux会是的Docker的安装出错。
  docker: Error response from daemon: failed to create endpoint registry on network bridge: iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 5000 -j DNAT --to-destination 172.17.0.2:5000 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1).

二、安装Docker Registry
  目前Docker Registry已经升级到了v2,最新版的Docker已不再支持v1。Registry v2使用Go语言编写,在性能和安全性上做了很多优化,重新设计了镜像的存储格式。
  1.官网安装 registry
   https://docs.docker.com/registry/
  2.使用Docker-compose安装(推荐)
  Docker-compose是一个非常有用的Docker运行,管理的工具。你可以通过定义compose文件,使用简单的一条命令同时起多个Docker Container运行不同的服务。Docker-compose对于开发,测试,环境保存以及CI都提供了非常大的便利。
  Docker-compose是用Python开发的一个工具,所以可以用pip直接安装。
$ pip install docker-compose
需要注意的是,docker-compose可能对requests module的版本有限制,而本机上可能安装了更高版本的requests模块,造成运行时报错。可以使用pip-conflict-checker检查版本冲突,卸载不合适的版本,重新安装一个合适的版本。
   $ pip install pip-conflict-checker
   $ pipconflictchecker
   $ pip uninstall requests
   $ pip install requests==2.7.0

  实际使用操作中使用pip安装的docker-compose可能在执行时还会报代码有bug。
  所以推荐直接从github中下载稳定的release版本安装。
  

$ curl -L https://github.com/docker/compose/releases/download/1.5.2/ \    docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose      $ chmod +x /usr/local/bin/docker-compose    $ ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 

  安装htpasswd
  因为需要使用nginx提供安全验证的功能,需要一个地方放置用户名和密码对。
  使用由httpd-tools提供的htpasswd工具生成用户名密码对。
  安装httpd-tools.

  $ yum install httpd-tools

三、运行Registry Container并使用Nginx做代理
  运行nginx和registry容器
  创建一个工作目录,例如/data/programs/docker,并在该目录下创建docker-compose.yml文件,将以下docker-compose.yml内容复制粘贴到你的docker-compose.yml文件中。
  内容大致意思为,基于“nginx:1.9” image运行nginx容器,暴露容器443端口到host 443端口。并挂载当前目录下的nginx/目录为容器的/etc/nginx/config.d目录。
  nginx link到registry容器。基于registry:2 image创建registry容器,将容器5000端口暴露到host 5000端口,使用环境变量指明使用/data为根目录,并将当前目录下data/文件夹挂载到容器的/data目录。
  

$ mkdir /data/programs/docker -p$ cd /data/programs/docker$ mkdir data && mkdir nginx $ cat /data/programs/docker/docker-compose.ymlnginx:    image: "nginx:1.9"    ports:      - 443: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  

  配置nginx
  在nginx目录中创建registry.conf文件配置nginx。配置nginx与registry的关系,转发端口,以及其他nginx的配置选项。复制,粘贴如下内容到你的registry.conf文件中:
  

$ cat /data/programs/docker/nginx/registry.confupstream 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 up运行registry和nginx容器。
  

$ docker-compose upStarting docker_registry_1Starting docker_nginx_1    (注:下面是log,注意格式编排)Attaching to docker_registry_1, docker_nginx_1registry_1 | time="2016-01-08T11:22:41Z" level=info msg="Starting upload purge in 7m0s" go.version=go1.5.2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1registry_1 | time="2016-01-08T11:22:41Z" 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." go.version=go1.5.2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1registry_1 | time="2016-01-08T11:22:41Z" level=info msg="redis not configured" go.version=go1.5.2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1registry_1 | time="2016-01-08T11:22:41Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.5.2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1registry_1 | time="2016-01-08T11:22:41Z" level=info msg="listening on 0.0.0.0:5000" go.version=go1.5.2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1registry_1 | time="2016-01-08T11:22:49Z" level=info msg="response completed" go.version=go1.5.2 http.request.host="localhost:5000" http.request.id=1455af27-cbf6-4ab2-8f22-4de35d2aa507 http.request.method=GET http.request.remoteaddr="192.168.42.1:39027" http.request.uri="/v2/" http.request.useragent="curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" http.response.contenttype="application/json; charset=utf-8" http.response.duration=3.108632ms http.response.status=200 http.response.written=2 instance.id=4c7af230-a76b-4235-9a8d-2e552c2dbab8 version=v2.2.1  

  执行docker-compose up后。注意是否有容器启动失败的消息,如果容器启动失败的消息,需要检查网络,是否能从dockerhub上pull image(需代理,或使用使用国内镜像,使用国内镜像需更改docker-compose.yml文件中image项)。也由可能粘贴配置文件错误,需仔细检查。
启动后也可以使用docker ps命令查看是否两个容器都正常运行。

$ docker psCONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                          NAMES28ac3aba9a22        nginx:1.9           "nginx -g 'daemon of   38 seconds ago      Up 37 seconds       80/tcp, 0.0.0.0:443->443/tcp   docker_nginx_1      0cddc713022f        registry:2          "/bin/registry /etc/   38 seconds ago      Up 37 seconds       127.0.0.1:5000->5000/tcp       docker_registry_1  

  确定docker容器都正常运行后,用curl 命令验证功能是否正常运行。使得localhost:5000和localhost:443访问registry都应该返回{}。
  

#都是返回{}curl http://localhost:5000/v2/  curl http://localhost:443/v2/  

  使用ctrl-c退出docker-compose,继续后面的步骤。
  添加用户名和密码
  在/data/programs/docker/nginx目录下执行下面命令创建用户名和密码对,如果要创建多个用户名和密码对,则不是使用“-c“选项。
  

$ htpasswd -c registry.password docker 然后修改Registry.conf文件,取消下面三行的注释。auth_basic "registry.localhost";  auth_basic_user_file /etc/nginx/conf.d/registry.password;  add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;  

  再次执行docker-compose up运行registry,这时使用localhost:5000端口访问得到的结果为”{}”,但是使用localhost:443访问将得到”401 Authorisation Required“的提示。加入用户名和密码验证才能得到与直接访问registry 5000端口相同的结果。
  

$ curl http://localhost:5000/v2/  {}$ curl http://localhost:443/v2/<html><head><title>401 Authorization Required</title></head><body bgcolor="white"><center><h1>401 Authorization Required</h1></center><hr><center>nginx/1.9.9</center></body></html>$ curl http://docker:123456@localhost:443/v2/{}

四、加入SSL验证
  如果你有经过认证机构认证的证书,则直接使用将证书放入nginx目录下即可。如果没有,则使用openssl创建自己的证书。
  进行/data/programs/docker/nginx目录
  生成一个新的root key
  

$ openssl genrsa -out devdockerCA.key 2048生成根证书(一路回车即可)$ openssl req -x509 -new -nodes -key devdockerCA.key -days 10000 -out devdockerCA.crt为server创建一个key。(这个key将被nginx配置文件registry.con中ssl_certificate_key域引用)$openssl genrsa -out domain.key 2048

  制作证书签名请求。注意在执行下面命令时,命令会提示输入一些信息,”Common Name”一项一定要输入你的域名(官方说IP也行,但是也有IP不能加密的说法),其他项随便输入什么都可以。不要输入任何challenge密码,直接回车即可。
  

$ openssl req -new -key domain.key -out dev-docker-registry.com.csrYou are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [XX]:State or Province Name (full name) []:Locality Name (eg, city) [Default City]:Organization Name (eg, company) [Default Company Ltd]:Organizational Unit Name (eg, section) []:Common Name (eg, your name or your server's hostname) []:docker-registry.comEmail Address []:Please enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []:  

  签署认证请求
  

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

  配置nginx使用证书
  修改registry.conf配置文件,取消如下三行的注释
  

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

  运行Registry
  执行docker-compose up -d在后台运行Registry,并使用curl验证结果。这时使用localhost:5000端口仍然可以直接访问Registry,但是如果使用443端口通过nginx代理访问,因为已经加了SSL认证,所以使用http将返回“400 bad request”
  

$ curl http://localhost:5000/v2/{}$ curl http://localhost:443/v2/<html><head><title>400 The plain HTTP request was sent to HTTPS port</title></head><body bgcolor="white"><center><h1>400 Bad Request</h1></center><center>The plain HTTP request was sent to HTTPS port</center><hr><center>nginx/1.9.9</center></body></html>

  应该使用https协议
  

$ curl https://localhost:443/v2/curl: (60) Peer certificate cannot be authenticated with known CA certificatesMore details here: http://curl.haxx.se/docs/sslcerts.htmlcurl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option.If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL).If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.

  由于是使用的未经任何认证机构认证的证书,并且还没有在本地应用自己生成的证书。所以此时会提示使用的是未经认证的证书,可以使用“-k”选项不进行验证。
  

$ curl -k https://localhost:443/v2/<html><head><title>401 Authorization Required</title></head><body bgcolor="white"><center><h1>401 Authorization Required</h1></center><hr><center>nginx/1.9.9</center></body></html>

五、Docker客户端使用Registry
  添加证书
  Centos 6/7 添加证书具体步骤如下
  

安装ca-certificates包$ yum install ca-certificates使能动态CA配置功能$ update-ca-trust force-enable 将key拷贝到/etc/pki/ca-trust/source/anchors/$ cp devdockerCA.crt /etc/pki/ca-trust/source/anchors/使新拷贝的证书生效$ update-ca-trust extract证书拷贝后,需要重启docker以保证docker能使用新的证书$ service docker restartDocker pull/push image测试制作要push到registry的镜像
#查看本地已有镜像$ docker imagesREPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZEregistry            2                   cd57aad0bd45        3 days ago          224.5 MBnginx               1.9                 813e3731b203        3 weeks ago         133.9 MB#为本地镜像打标签$ docker tag registry:2 docker-registry.com/registry:2$ docker tag nginx:1.9 docker-registry.com/nginx:1.9$ docker imagesREPOSITORY                     TAG                 IMAGE ID            CREATED             VIRTUAL SIZEregistry                       2                   cd57aad0bd45        3 days ago          224.5 MBdocker-registry.com/registry   2                   cd57aad0bd45        3 days ago          224.5 MBnginx                          1.9                 813e3731b203        3 weeks ago         133.9 MBdocker-registry.com/nginx      1.9                 813e3731b203        3 weeks ago         133.9 MBpush测试#不登陆直接push镜像到registry,会提示失败[root@PRO-REGISTRY-220 ~]# docker push docker-registry.com/registryThe push refers to a repository [docker-registry.com/registry] (len: 1)cd57aad0bd45: Image push failedcd57aad0bd45: Buffering to DiskPlease login prior to push:Username:Error response from daemon: no successful auth challenge for https://docker-registry.com/v2/ - errors: [basic auth attempt to https://docker-registry.com/v2/ realm "registry.localhost" failed with status: 401 Unauthorized]#登陆后,再试$docker login https://docker-registry.comUsername: dockerPassword:Email:WARNING: login credentials saved in /root/.docker/config.jsonLogin Succeeded #可以push 镜像到registry$ docker push docker-registry.com/registryThe push refers to a repository [docker-registry.com/registry] (len: 1)cd57aad0bd45: Image already existsb3c39a7768ea: Image successfully pushed4725a48b84d4: Image successfully pushed7b4078296418: Image successfully pushed7bd663e30ad0: Image successfully pushed28864e830e4d: Image successfully pushed7bd2d56d8449: Image successfully pushedaf88597ec24b: Image successfully pushedb2ae0a712b39: Image successfully pushed02e5bca4149b: Image successfully pushed895b070402bd: Image successfully pushedDigest: sha256:92835b3e54c05b90e416a309d37ca02669eb5e78e14a0f5ccf44b90d4c21ed4c搜索镜像curl https://docker:123456@docker-registry.com/v2/_catalog{"repositories":["registry"]}curl https://docker:123456@docker-registry.com/v2/nginx/tags/list{"name":"registry","tags":["2"]} pull测试$ docker logout https://docker-registry.comRemove login credentials for https://docker-registry.com#不登陆registry直接pull镜像也会失败$ docker pull docker-registry.com/registry:2Pulling repository docker-registry.com/registryError: image registry:2 not found#登陆后再测试$ docker login https://docker-registry.comUsername: dockerPassword:Email:WARNING: login credentials saved in /root/.docker/config.jsonLogin Succeeded#登陆后可以pull$ docker pull docker-registry.com/registry:21.9: Pulling from dev-docker-registry.com/registry6d1ae97ee388: Already exists8b9a99209d5c: Already exists3244b9987276: Already exists50e5c9c52d5d: Already exists146400830f31: Already existsb412cc1cde63: Already exists7fe375038652: Already existsc43f11a030f9: Already exists152297b50994: Already exists01e808fa2993: Already exists813e3731b203: Already existsDigest: sha256:af688d675460d336259d60824cd3992e3d820a90b4f31015ef49dc234a00adc3Status: Downloaded newer image for docker-registry.com/registry:2

六、CentOS 7安装Docker及常用命令

yum install docker    #安装dockersudo systemctl daemon-reload    #启动docker-daemonsudo systemctl restart docker     #重启启动dockersystemctl start docker.service     #启动dockersystemctl enable docker.service    #docker开机启动docker -v     #查看docker版本docker info     #查看docker具体信息docker pull centos     #下载centos imagedocker images     #显示已有imagedocker rmi  imageid     #删除imagesudo usermod -a -G docker wisely     #非root用户使用docker run -i -t centos /bin/bash     #启动系统docker stop $(docker ps -a -q)     #停止所有容器docker rm $(docker ps -a -q)      #删除所有container docker rmi $(docker images -q)     #删除所有imagedocker inspect container_name     #查看容器信息 docker inspect container_name | grep IPAddress     #查看当前容器ip地地址docker attach --sig-proxy=false 304f5db405ec      (按control +c 退出不停止容器)
1 0
原创粉丝点击