本文实验的环境
- 本地端为自己的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/:这个只是取消掉另一个上传的进程罢了。