一.Dockerfile语法梳理及最佳实践
1,关键字
二.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"
- 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"]
2.CMD
3.ENTRYPOINT
三.镜像的发布
- Docker hub[类似于GitHub]
- 可以使用
docker pull image名称
从registry上拉取image
- 向Docker hub中提交代码[前缀名需要时docker hub的用户名]
- 可以在Docker hub中创建repository时关联github的代码仓库存储dockerfile,每次pull时,dockerhub会自动进行build(每次维护dockerfile文件即可)
- 如何公司搭建自己的Docker registry,供公司内部使用的?
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<mrjackzhe@gmail.com>"
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 指定大小
3.Linux底层对docker的技术支持
- Namespaces:做隔离pid,net,ipc,mnt,uts
- Control groups:做资源限制
- Union file system:Container和image的分层