注:原文做者是 Alex Ianchici,原文地址是 Docker private registry authenticationhtml
安全已经融入了咱们的生活。咱们锁门,使用密码保护咱们的银行信息,可是一般密码如此复杂以致于形成咱们很容易忘记它。用常识来保护系统的安全是良好的实践。这真的很容易呈现,由于它是一个内部的系统,没有必要启用身份认证以及安全传输,但在咱们当前的远程工做时代,内部网络可能十分普遍。node
考虑到这一点,咱们花费了一些时间审查了咱们维护的多种系统,并在这星期,我给咱们的私人 Docker 注册中心设置了添加身份认证的目标。你也许知道,Docker 注册没有提供身份认证的方法。所以咱们决定早期的方案就是在咱们的镜像仓库前面加一个身份认证的代理。在咱们的案例中,咱们决定经过 SSL 使用 Nginx 并加上一个内部身份认证 API。nginx
该解决方案的几个优点:git
我把一个简单的身份认证服务和一个 Nginx 容器放在一块儿,咱们能够在 github 上获取可用的版本(https://registry.hub.docker.com/u/opendns)。github
做为 Nginx 代理容器的一个参考,咱们使用 NodeJS 构建了一个身份认证 API,很是容易的建立了一个基础身份认证服务。全部咱们所须要作的就是建立一个真正简单的 server.js,使用 htpasswd utility 生成一个资格证书文件,而且在一个 Docker 容器中封装,咱们能够建立以下 Dockerfile:web
FROM google/nodejs ADD . /app WORKDIR /app RUN npm install http-auth EXPOSE 8000 ENV NODE_PATH /data/node_modules/ CMD ["node", "server.js"]
而后咱们测试并部署咱们的服务:docker
ubuntu@trusty-64:/basic-auth# docker build -t opendns/basic-auth-service . ubuntu@trusty-64:/basic-auth# docker run --name simple-auth opendns/basic-auth-service ubuntu@trusty-64:/basic-auth# docker inspect --format '{{ .NetworkSettings.IPAddress }}' simple-auth 172.17.0.40 ubuntu@trusty-64:/basic-auth# curl 172.17.0.40:8000 401 Unauthorized ubuntu@trusty-64:/basic-auth# curl -u testuser:testpassword 172.17.0.40:8000 User authenticated successfully
你能够在这里找到基础身份认证服务的全部示例代码,可用的容器在这里。npm
Nginx 代理的关键部分是配置文件:ubuntu
# define an /auth section to send the request to an authentication service location = /auth { proxy_pass {{auth_backend}}; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Docker-Token ""; } # use the auth_request directive to redirect all requests to the /auth section above location / { proxy_pass {{backend}}; auth_request /auth; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; proxy_buffering off; }
使用了 http_auth_request 模块发送用户,使用 proxy_pass 指令转发请求到咱们简单身份认证服务处理,返回 200 或是 401。 401 受权响应触发 Docker 客户端回应一组使用基自己份验证的凭据。一旦证书被接受,API 将返回 200。Nginx 能够发送请求到私有注册中心,把这两个容器放在一块儿:安全
ubuntu@trusty-64:/nginx-auth-proxy# docker run -d --name hello-world hello-world # run a simple web server that prints out “Hello world” ubuntu@trusty-64:/nginx-auth-proxy# docker inspect --format '{{ .NetworkSettings.IPAddress }}' hello-world 172.17.0.41 ubuntu@trusty-64:/nginx-auth-proxy# docker run -d -e AUTH_BACKEND=http://172.17.0.40:8000 -e BACKEND=http://172.17.0.41:8081 -p 0.0.0.0:8080:80 nginx-auth ubuntu@trusty-64:/nginx-auth-proxy# curl 0.0.0.0:8080 <html> <head><title>401 Authorization Required</title></head> <body bgcolor="white"> <center> <h1>401 Authorization Required</h1> </center> <hr> <center>nginx/1.6.1</center> </body> </html> ubuntu@trusty-64:/nginx-auth-proxy# curl -u testuser:testpassword 0.0.0.0:8080 Hello world
惟一剩下的事情是给这些容器添加 SSL 证书,而后你就能够好好的玩耍了。你能够在这里找到 Nginx 身份认证代理的代码,在这里是可用的容器。使用这个方案须要注意几件事:
该解决方案另一个有趣的附带影响就是,在私有注册中心启用 SSL 已经下降了每一个 pull 请求花费的时间,好比,除非在注册中心的 URL 上指定了端口,不然在链接 80 端口以前,客户端首先初始化尝试链接 443 端口。