注:原文做者是 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 端口。