版权声明:作者已开启版权声明,如转载请注明转载地址。 https://blog.csdn.net/qq_34829447/article/details/85493941
一.Dockerfile语法梳理及最佳实践
1,关键字
- FROM
- 用在Dockerfile的开头,用来设定docker image的base image,想在哪个base image之上build我们自己的image
- 尽量使用官方提供的image作为base image,因为安全
- 示例代码
FROM scratch #从头制作base image FROM centos #使用centos作为base image FROM ubuntu:14.04 #选择其他的image作为base image
- LABEL
- 定义image的meta data,用来书写帮助信息
- 示例代码
LABEL maintainer="[email protected]"#定义作者 LABEL version="1.0"#定义版本 LABEL description="This is description"#定义描述
- RUN
- RUN用于运行命令
- 每次运行RUN都会增加一个分层。为了美观,复杂的RUN请用反斜线换行!避免无用分层,合并多条命令成一行(用&&)。
- 示例代码
RUN yum update&&yum install -y vim \ python-dev #反斜线表示换行 RUN apt-get update&&apt-get install -y perl \ pwgen --no-install-recommends&&rm -rf \ /var/lib/apt/lists/* #注意清理cache RUN /bin/bash -c 'source $HOME/.bashrc;echo $HOME'
- WORKDIR
- WORKDIR用于设定当前工作目录,类似于cd到指定目录
- 示例代码
WORKDIR /root #进入到root文件夹下 WORKDIR /test #如果没有自动创建test目录 WORKDIR demo RUN pwd #结果输出应该是/test/demo
- 用WORKDIR,不要用RUN cd!用WORKDIR应尽量使用绝对目录!
- ADD and COPY
- COPY可以把本地的文件添加到Docker image里面;ADD可以把本地文件添加到目的地址并解压缩
- 示例代码
ADD hello / #将当前目录中的hello添加到image的根路径下 ADD test.tar.gz / #添加到根目录并解压 WORKDIR /root ADD hello test/ #hello的路径是/root/test/hello WORKDIR /root COPY hello test/
- 大部分的情况下,COPY优于ADD!ADD除了COPY还有额外功能(解压)!添加远程文件/目录请使用curl或者wget!
- ENV
- ENV设定环境变量(常量)
- 示例代码
ENV MYSQL_VERSION 5.6 #设置常量 RUN apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* #引用常量
- 尽量使用ENV,可以增加代码的可维护性
- VOLUME and EXPOSE
- 用于存储和网络
二.RUN vs CMD vs ENTRYPOINT
- RUN:执行命令并创建新的Image Layer
- CMD:设置容器启动后默认执行的命令和参数
- ENTRYPOINT:设置容器启动时运行的命令
1.Shell和Exec格式
- Shell格式[把要运行的命令当成shell命令去执行]
RUN apt-get install -y vim CMD echo "hello docker" ENTRYPOINT echo "hello docker"
- Exec格式[通过特定的格式指明要运行的命令,以及命令的参数]
RUN ["apt-get","install","-y","vim"] CMD ["/bin/echo","hello docker"] ENTRYPOINT ["/bin/echo","hello docker"]
- Dockerfile1示例代码
FROM centos ENV name Docker ENTRYPOINT echo "hello $name"
- 结果是hello Docker
- Dockerfile2示例代码
FROM centos ENV name Docker ENTRYPOINT ["/bin/echo","hello $name"]
- 结果是hello $name
- 执行的是单纯的echo命令,而不是执行shell的echo命令,所以拿不到环境变量的值
- 如果想执行shell中的echo则应修改dockerfile如下
FROM centos ENV name Docker ENTRYPOINT ["/bin/bash","-c","echo hello $name"]
- 结果是hello Docker
2.CMD
- 容器启动时默认执行的命令
- 如果docker run指定了其他命令,CMD命令被忽略
- 如果定义了多个CMD,只有最后一个会执行
- 示例代码
FROM centos ENV name Docker CMD echo "hello $name"
- 当执行
docker run [image]
时输出:hello Docker
- 当执行
docker run -it [image] /bin/bash
时输出:被忽略掉
- 当执行
3.ENTRYPOINT
- 让容器以应用程序或者服务的形式运行[通常用于启动后台的进程,比如启动mysql服务器]
- 不会被忽略,一定会执行
- 最佳实践:写一个shell脚本作为entrypoint
COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] EXPOSE 27017 CMD ["mongod"]
三.镜像的发布
- Docker hub[类似于GitHub]
- 可以使用
docker pull image名称
从registry上拉取image
- 可以使用
- 向Docker hub中提交代码[前缀名需要时docker hub的用户名]
- 执行
docker login
进行登陆 - 执行
docker image push
进行提交[简写:docker push
] - 提交实例
docker push wangzhejack/hello:latest
- 提交成功后可以到docker hub的repositories中查看,其中latest是设置tag
- 测试发布是否成功
docker rmi id号 #删除本地image docker image ls #查看本地image是否删除hello镜像 docker pull wangzhejack/hello #从远程仓库拉取hello镜像 docker image ls #查看本地image是否存在hello镜像
- 执行
- 可以在Docker hub中创建repository时关联github的代码仓库存储dockerfile,每次pull时,dockerhub会自动进行build(每次维护dockerfile文件即可)
- 如何公司搭建自己的Docker registry,供公司内部使用的?
- 执行
docker run -d -p 5000:5000 --restart always --name registry registry:2
启动私有的registry【启动在5000端口上】 - 每次提交前的build变成
docker build -t ip地址:端口号/image名 .
- 此时计算机可能会觉得指定的ip的dockerhub是不可信任不安全的,需要执行以下操作
- 在/etc/docker文件夹下创建daemon.json文件,并添加如下内容,表示信任以下registry
{"insecure-registries":["ip地址:端口号"]}
- 执行
sudo vim /lib/systemd/system/docker.service
,添加以下内容:EnvironmentFile=~/etc/docker/daemon.json
表示当运行docker服务的时候会读取daemon.json文件,从而加载对应registry - 执行
sudo service docker restart
重启docker服务
- 执行
docker push ip地址:端口号/image名
向自己的仓库中push - 执行
docker pull ip地址:端口号/image名
从自己的仓库中pull
- 执行
4.Dockerfile实战:将python程序打包成docker image,再将image运行成container
- 将如下python的web项目打包成docker image,之后运行成container
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "hello docker" if __name__ == "__main__": app.run()
- 创建Dockerfile文件
FROM python:2.7 #使用python2.7版本的image作为base image LABEL maintainer="Jack<[email protected]>" RUN pip install flask #在container上安装flask COPY app.py /app/ WORKDIR /app EXPOSE 5000 CMD ["python","app.py"]
- 如果程序直接运行则会运行在image的127.0.0.1的5000端口上,只能image内可访问。所以需要使用EXPOSE将运行的container的指定端口暴漏出来。
- 因为每次执行的时候都会创建image,所以如果其中某一步出现问题,可以取上一步的id值进行交互式run测试查看是否进行了对应的操作
docker run -it ID值 /bin/bash
- 执行
docker run wangzhejack/flask-hello-world -d
运行image创建container(-d表示后台执行,用docker ps
可以查看)
四.容器的操作
1.对运行中的容器执行命令docker exec 命令
- 执行
docker exec -it containerID号 命令内容
其中-it表示执行交互式命令 - 例
docker exec -it be393ca08145 /bin/bash
进入指定container中的交互式命令行中 - 例
docker exec -it be393ca08145 python
进入container并执行python进入python交互式命令行中
2.停掉运行中的容器
docker container stop containerID
其中containerID也可以是name- 简写
docker stop contianerID
其中containerID也可以是name
3.清理停掉的容器
docker rm $(docker ps -aq)
4.指定docker运行的container的名字
docker run -d --name=demo wangzhejack/flask-hello-world
指定运行container的名字为demo,如果不指定则会自动分配一个name
5.启动container容器
docker start containerID/name
启动容器可以使用id或是name
6.显示container详细信息
docker inspect containerID/name
查看container详细信息时可以使用id或name
7.查看container运行产生的输出日志
docker logs containerID/name
查看container的日志记录可以使用id或name
2.通过Dockerfile运行一个linux的命令行工具实战
1.在ubuntu的image的container上安装stress
docker run -it ubuntu #启动ubuntu的image,创建container
apt-get update&&apt-get install -y stress #安装stress
2.stress工具的应用
stress --vm1
启动一个worker(创建要给进程),默认分配的内存是256M
3.将stress打包成一个docker image
FROM ubuntu
RUN apt-get update&&apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress"]
CMD []
* 使用ENTRYPOINT+空CMD的方式可以使输入的时候携带指定的参数
* 例如,执行`docker run -it wangzhejack/stress-test --vm 1`则会执行`stress --vm 1`的命令
五.容器的资源限制(防止使用过大内存的container导致内存溢出)
- 执行
docker run
时可以通过参数进行资源的限制,如指定cpu的个数/内存的大小等
1.设置container的内存限制--memory=指定大小
docker run --memory=200M wangzhejack/stress-test --vm 1 --verbose
其中–verbose相当于debug模式启动vm压力,vm 1的默认分配内存为256M,因为memory给了200M,默认情况下的memory wrap与memory相等,则相当于container有400M,其中有进程占用256M,则可以正常运行docker run --memory=200M wangzhejack/stress-test --vm 1 --verbose --vm-bytes 500M
则相当于container有400M,其中有进程占用500M,运行container时会提示run失败
2.设置container的cpu使用情况--cpu-shares 指定大小
- 通过
--cpu-shares int
设定cpu shares的权重值,是多个contianer之间的相对权重比较,当同时启用时,根据cpu shares权重比划分cpu - 实例测试
#启用三个container占用cpu docker run --cpu-shares=5 --name=demo1 wangzhejack/stress-test --cpu 1 docker run --cpu-shares=10 --name=demo2 wangzhejack/stress-test --cpu 1
- 其中
--cpu 1
表示运行的container通过stress工具占用cpu - 再启动一个container,通过top查看内存则可以发现,当只运行一个container时cpu占用近乎100%,当同时运行了第二个container时,由于设置的cpu占用权重比时5:10,则可以看到第一个stress占用33%左右,第二个占用66%左右
- 其中
3.Linux底层对docker的技术支持
- Namespaces:做隔离pid,net,ipc,mnt,uts
- Control groups:做资源限制
- Union file system:Container和image的分层