本文实验的环境
- 本地端为自己的Mac笔记本电脑
- 云端为Ubuntu Server 14.04
- 本地与云端都需要安装Docker,按照官网文档安装:https://docs.docker.com/engine/installation/
在本地制作Docker镜像
本步骤环境为本地Mac。
编写Dockefile,将我们的python api server打包成一个镜像:
$ cd ~/etc/docker/ $ cat Dockerfile
FROM alpine:3.5 RUN apk add --no-cache python && \ python -m ensurepip && \ rm -r /usr/lib/python*/ensurepip && \ pip install --upgrade pip setuptools && \ rm -r /root/.cache && \ apk add --no-cache vim py-mysqldb musl-dev linux-headers g++ python-dev libxml2-dev \ libxml2 libxslt libxslt-dev && \ ln -s /usr/include/locale.h /usr/include/xlocale.h ############## COPY VikiQA/requirements.txt /src/ RUN pip install -r /src/requirements.txt COPY VikiQA /src/VikiQA COPY VikiAIML /src/VikiAIML RUN cd /usr/lib/python2.7/site-packages && ln -s /src/VikiQA/viki_qa . && \ cd /src/VikiQA/viki_qa && cp config_sample.py config.py && \ mkdir /var/log/viki_qa WORKDIR /src/VikiQA/viki_qa/ ENTRYPOINT ["/usr/bin/gunicorn", "-k", "tornado", "-b", "0.0.0.0:80", "--workers=4", "viki_qa.wsgi:app"]
然后制作好镜像:
$ cd ~/etc/docker/ $ docker build -t kyle/viki_qa .
完成后,可以通过命令查看制作好的镜像:
$ docker images kyle@kyledeMacBook-Pro ~/p/a/VikiDocker> docker images REPOSITORY TAG IMAGE ID CREATED SIZE kyle/viki_qa latest 5cd56c45db67 27 hours ago 347 MB
在云端运行Docker registry
本步骤环境为云端Ubuntu Server。
假设云端服务器地址为 docker.kyle.ai,在上面安装好docker后,运行registry容器,这里我们用docker-compose来运行。
$ cd ~/etc/docker/ $ cat docker-compose.yml
version: '2' services: registry: image: registry:2 restart: always ports: - 5000:5000 volumes: - /home/deploy/data/docker/registry:/var/lib/registry # - /home/deploy/etc/docker/cert/:/certs # - /home/deploy/etc/docker/auth/:/auth # environment: # REGISTRY_HTTP_TLS_CERTIFICATE: /certs/214053375670003.pem # REGISTRY_HTTP_TLS_KEY: /certs/214053375670003.key # REGISTRY_AUTH: htpasswd # REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd # REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm container_name: registry
解释一下,就是在本地运行registry窗口服务,端口号为5000,并把仓库的文件数据持久化到本地磁盘 /home/deploy/data/docker/registry 。
注释的那些行,是用来配置使用auth认证与ssl证书的,但由于我们使用nginx来做这个事情,所以docker registry服务就不用了。不能nginx与registry同时配置这两个,不然会访问不成功。
然后把容器运行起来
$ cd ~/etc/docker/ $ sudo docker-compose up -d $ sudo docker-compose ps Name Command State Ports -------------------------------------------------------------------------- registry /entrypoint.sh /etc/docker ... Up 0.0.0.0:5000->5000/tcp
下一步就需要配置nginx,将服务器的80端口转发到registry服务的5000端口,并设置好ssl与auth认证。
nginx配置文件如下:
$ cd ~/etc/nginx/sites-enabled/ $ cat docker.kyle.ai
server { listen 80; listen 443 ssl; ssl_certificate /etc/nginx/cert/docker.kyle.ai/ssl.pem; ssl_certificate_key /etc/nginx/cert/docker.kyle.ai/ssl.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; add_header X-Frame-Options SAMEORIGIN; add_header Strict-Transport-Security "max-age=8640000;"; add_header X-Content-Type-Options: nosniff; server_name docker.kyle.ai; access_log /var/log/nginx/docker-access.log; error_log /var/log/nginx/docker-error.log; root /home/deploy/www/; client_max_body_size 0; # 不限制上传文件的大小,一个镜像可能有几百M chunked_transfer_encoding on; if ($ssl_protocol = "") { return 302 https://$server_name$request_uri; } location ^~ / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; } upstream docker_registry{ server 127.0.0.1:5000; } 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; } auth_basic "Registry realm"; auth_basic_user_file /home/deploy/etc/docker/auth/htpasswd; add_header 'Docker-Distribution-Api-Version' 'registry/2.0'; 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; } }
ssl证书,我是直接在阿里云申请的免费dv证书,申请地址:https://common-buy.aliyun.com/?commodityCode=cas#/buy
申请成功后,相应的配置 ssl_certificate 与 ssl_certificate_key 文件路径。
然后就是basic auth的用户文件:/home/deploy/etc/docker/auth/htpasswd,可以通过如下命令生成:
sudo docker run --entrypoint htpasswd registry:2 -bn username password > htpasswd
注意不要添加-B参数,之前我用的 -Bbn 参数,结果后面nginx会出现如下错误:
[crit] 12472#0: *29935 crypt_r() failed (22: Invalid argument)
nginx的这个配置,可能跟nginx版本有关系
add_header 'Docker-Distribution-Api-Version' 'registry/2.0';
高版本的nginx可能需要在后面添加个 always
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
配置好nginx后,就可以通过访问api来测试: curl https://docker.kyle.ai/v2 这样,这里我只是用了示例域名,你需要换成你自己的。
将本地的image push到云端的registry
本步骤是在本地Mac系统环境。
上面的步骤中,我们已经成功地在本地build了一个Image,叫 kyle/viki_qa,现在把这个image映射到云端的registry:
$ sudo docker tag kyle/viki_qa docker.kyle.ai/kyle/viki_qa
然后 push 到云端:
$ sudo docker push docker.kyle.ai/kyle/viki_qa Error: Status 405 trying to push repository kyle/viki_qa: "<html>\r\n<head><title>405 Not Allowed</title>
报405 Not Allowed的错误, 是由于需要先登陆,还记得我们在上面配置nginx的时候,设置的basic auth的用户与密码,用这个来登陆一下
$ sudo docker login docker.kyle.ai 输入密码与密码
之后再push就行了。
在其它机器拉取我们的镜像
直接
$ sudo docker pull docker.kyle.ai/kyle/viki_qa $ sudo docker run -it --rm -d docker.kyle.ai/kyle/viki_qa
其它
删除远程的image比较麻烦,官方没有提供很好的办法。
目前docker官方提供了如下3个软删除的方法:
- DELETE:/v2//manifests/:这个API是软删除一个清单(manifest),但是真正占用存储空间的层还在。
- DELETE:/v2//blobs/:这个API类似上面那个,只不过它要软删除的对象是层(layer)罢了。
- DELETE:/v2//blobs/uploads/:这个只是取消掉另一个上传的进程罢了。