docker部署实战
检查docker镜像
$ ps -aux | grep -v grep | grep docker-proxy
查看被docker-proxy占用的端口
停止 doker 进程,删除所有容器,然后删除 local-kv.db 这个文件,再启动 docker 就可以了。
$ sudo service docker stop $ docker rm $(docker ps -aq) $ sudo rm /var/lib/docker/network/files/local-kv.db $ sudo service docker start
这个应用的代码部分(app.py)非常简单:
from flask import Flask import socket import os app = Flask(__name__) @app.route('/') def hello(): html = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname()) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)
在这段代码中,我使用 Flask 框架启动了一个 Web 服务器,而它唯一的功能是:如果当前环境中有“NAME”这个环境变量,就把它打印在“Hello”之后,否则就打印“Hello world”,最后再打印出当前环境的 hostname。这个应用的依赖,则被定义在了同目录下的 requirements.txt 文件里,内容如下所示:
$ cat requirements.txt
Flask
而将这样一个应用容器化的第一步,是制作容器镜像。不过,相较于我之前介绍的制作 rootfs 的过程,Docker 为你提供了一种更便捷的方式,叫作 Dockerfile,如下所示。
# 使用官方提供的Python开发镜像作为基础镜像 FROM python:2.7-slim # 将工作目录切换为/app WORKDIR /app # 将当前目录下的所有内容复制到/app下 ADD . /app # 使用pip命令安装这个应用所需要的依赖 RUN pip install --trusted-host pypi.python.org -r requirements.txt # 允许外界访问容器的80端口 EXPOSE 80 # 设置环境变量 ENV NAME World # 设置容器进程为:python app.py,即:这个Python应用的启动命令 CMD ["python", "app.py"]
通过这个文件的内容,你可以看到 Dockerfile 的设计思想,是使用一些标准的原语(即大写高亮的词语),描述我们所要构建的 Docker 镜像。并且这些原语,都是按顺序处理的。比如 FROM 原语,指定了“python:2.7-slim”这个官方维护的基础镜像,从而免去了安装 Python 等语言环境的操作。否则,这一段我们就得这么写了:
FROM ubuntu:latest RUN apt-get update -yRUN apt-get install -y python-pip python-dev build-essential ...
其中,RUN 原语就是在容器里执行 shell 命令的意思。而 WORKDIR,意思是在这一句之后,Dockerfile 后面的操作都以这一句指定的 /app 目录作为当前目录。所以,到了最后的 CMD,意思是 Dockerfile 指定 python app.py 为这个容器的进程。这里,app.py 的实际路径是 /app/app.py。所以,CMD ["python", "app.py"]等价于"docker run <image> python app.py"。另外,在使用 Dockerfile 时,你可能还会看到一个叫作 ENTRYPOINT 的原语。实际上,它和 CMD 都是 Docker 容器进程启动所必需的参数,完整执行格式是:“ENTRYPOINT CMD”。但是,默认情况下,Docker 会为你提供一个隐含的 ENTRYPOINT,即:/bin/sh -c。所以,在不指定 ENTRYPOINT 时,比如在我们这个例子里,实际上运行在容器里的完整进程是:/bin/sh -c "python app.py",即 CMD 的内容就是 ENTRYPOINT 的参数。备注:基于以上原因,我们后面会统一称 Docker 容器的启动进程为 ENTRYPOINT,而不是 CMD。需要注意的是,Dockerfile 里的原语并不都是指对容器内部的操作。就比如 ADD,它指的是把当前目录(即 Dockerfile 所在的目录)里的文件,复制到指定容器内的目录当中。读懂这个 Dockerfile 之后,我再把上述内容,保存到当前目录里一个名叫“Dockerfile”的文件中:
$ ls
Dockerfile app.py requirements.txt
接下来,我就可以让 Docker 制作这个镜像了,在当前目录执行:
$ docker build -t helloworld .
其中,-t 的作用是给这个镜像加一个 Tag,即:起一个好听的名字。docker build 会自动加载当前目录下的 Dockerfile 文件,然后按照顺序,执行文件中的原语。而这个过程,实际上可以等同于 Docker 使用基础镜像启动了一个容器,然后在容器中依次执行 Dockerfile 中的原语。需要注意的是,Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层。即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的。docker build 操作完成后,我可以通过 docker images 命令查看结果:
$ docker image ls
REPOSITORY TAG IMAGE ID
helloworld latest 653287cdf998
接下来,我使用这个镜像,通过 docker run 命令启动容器:
$ docker run -p 4000:80 helloworld
在这一句命令中,镜像名 helloworld 后面,我什么都不用写,因为在 Dockerfile 中已经指定了 CMD
同时,我已经通过 -p 4000:80 告诉了 Docker,请把容器内的 80 端口映射在宿主机的 4000 端口上。这样做的目的是,只要访问宿主机的 4000 端口,我就可以看到容器里应用返回的结果:
$ curl http://localhost:4000 <h3>Hello World!</h3><b>Hostname:</b> 4ddf4638572d<br/>
上传到dockerhub
我们可以将image上传到dockerhub中,从而能够在任何地方运行image。 首先我们需要先注册一个账号,然后输入docker login在本地登录账号 使用镜像加速器 直接访问dockerhub时,访问速度会较慢,这时候可以采用镜像加速器。国内的镜像加速器有 Azure 中国镜像 https://dockerhub.azk8s.cn 七牛云加速器 https://reg-mirror.qiniu.com 阿里云加速器(需登录账号获取) 在/etc/docker/daemon.json中写入以下内容 { "registry-mirrors": [ "https://dockerhub.azk8s.cn", "https://reg-mirror.qiniu.com" ] } 之后重启服务 $ sudo systemctl daemon-reload $ sudo systemctl restart docker 执行docker info可以查看镜像是否添加成功 $ docker info ... Registry Mirrors: https://dockerhub.azk8s.cn/ https://reg-mirror.qiniu.com/ Live Restore Enabled: false 关联仓库 使用username/repository:tag可已将本地image和远程仓库关联到一起,其中tag是可选的,当tag时,仓库会为相应的image打上标签。其完整的指令是 docker tag image username/repository:tag 例如 docker tag friendlyhello yezh01/getstart:v1.0 $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE friendlyhello latest 7ecc82fd960a 23 hours ago 148MB yezh01/getstart v1.0 7ecc82fd960a 23 hours ago 148MB python 2.7-slim 5f759d36aead 30 hours ago 137MB hello-world latest fce289e99eb9 7 months ago 1.84kB 检查image可以发现其中多了一个yezh01/getstart 上推image 我们需要先将image上传到dockerhub中,才能在不同机器上运行image,上传指令为: $ docker push yezh01/getstart:v1.0 上传完成后,,我们可以通过在任何机器上通过以下命令运行image docker run -p 4000:80 username/repository:tag
docker常规---启动停止关闭重启
一、启动一个已经停止的容器实例 docker start 容器ID或容器名,建议使用容器ID,容器ID支持模糊查询而容器名称不支持 1. 先查看已经暂停的容器实例信息 2. 通过docker start 067启动容器 3. 通过docker ps 查看当前启动的容器 具体操作如下图 docker start 还有两个参数 -it:以 交互模式启动 sudo docker run -it -p 8009:80 apinetcoredocker:1.0.0 -p 8009:80指将外部访问8009映射到内部的80端口,apinetcoredocker:1.0.0指镜像名称 因为是交互模式所以当前会话不支持继续输入命令工作,如果想看主机上的其他信息,可以考虑重新开启一个会话 -d:以 附加进程方式启动 sudo docker run -d -p 8009:80 apinetcoredocker:1.0.0 -d参数指用附加进程方式启动容器,上面的方法如不指定容器名称,系统会默认创建,如需要指定容器名称,添加--name 参数 sudo docker run -d -p 8009:80 --name testcore apinetcoredocker:1.0.0 执行命令界面 测试结果页面 进入docker容器里面,本人环境为ubuntu环境 sudo docker exec -it 067 /bin/bash 067指的是容器ID前3位,这里是模糊查询 执行后会显示/app#,这时我们通过curl 127.0.0.1:80/api/values ,查看显示运行是否正常,退出直接输入exit 二、停止一个正在运行的容器 1、docker stop 此方式常常被翻译为优雅的停止容器 docker stop 容器ID或容器名 参数 -t:关闭容器的限时,如果超时未能关闭则用kill强制关闭,默认值10s,这个时间用于容器的自己保存状态 docker stop -t=60 容器ID或容器名 2、docker kill docker kill 容器ID或容器名 :直接关闭容器 由此可见stop和kill的主要区别:stop给与一定的关闭时间交由容器自己保存状态,kill直接关闭容器 想更进一步了解处理机制的可以看下面这篇文章,比较详细但是需要其他方面的 https://www.jb51.net/article/96617.htm 三、重启一个容器 docker restart 容器ID或容器名 :不管容器是否启动,直接重启容器 1. 首先 docker ps 查看正在运行的容器信息,显示2分钟前启动运行 2. docker restart 59ec 重启容器 3. 再次 docker ps 查看容器信息 显示 2秒前启动运行 docker restart 参数 -t:关闭容器的限时,如果超时未能关闭则用kill强制关闭,默认值10s,这个时间用于容器的自己保存状态 原文地址:https://blog.csdn.net/Michel4Liu/article/details/80889977
浙公网安备 33010602011771号