写在前面
最为基础重要的两大概念:镜像和容器
Docker 底层技术支持:
Namespaces : 做隔离pid/net/ipc/mnt/uts
Control Groups : 做资源限制
Union file systems: Container 和 image 的分层
镜像Image
Image的获取方式(1):
(1)Build from Dockerfile
Dockerfile 有自己的语法
docker pull hello-world
docker image ls
发现只有1.85k,但是它任然是一个 Base Image
docker run hello-world
DIY一个:
mkdir hello-world
cd hello-world
vim hello.c
#include<stdio.h>
int main(){
printf("hello world!")
}
yum -y install gcc glibc-static
gcc -o hello hello.c
./hello
# 创建 Dockerfile ,构成一个Base Image
vim Dockerfile
FROM scratch
ADD hello /
CMD ["/hello"]
# 构建build:docker build -t liuge36/hello-world .
#查看分层:docker history 796a6f9eb6a1
docker run liuge36/hello-world 就变成了一个container
Image的获取方式(2):
(2)Pull from registry
仓库中拉取image,默认的仓库是docekr hub
docker push 推的话就需要注册docker hub
docker pull ubuntu:14.04
docker images
docker image rm imgaeID
docker rmi imageID
√ √ √ √ √ √ √ 小技巧:普通用户不加sudo 来执行docker的命令 √ √ √ √ √ √ √ √
sudo groupadd docker // 创建一个组
sudo gpasswd -a vagrant docker // 将用户添加到docker用户组里面
sudo service docker restart
重新登录 vagrant ssh
----------------------3.4 容器container--------
container 通过Image 创建(copy)
Image 本身是只读的
在Image layer 之上建立一个container layer(便成为 可读写)
类比面向对象中的内容就是: 类(image) 和 实例(container)
Image 负责app的存储和分发,Container 负责运行app
打印出本地正在运行的容器:
docker container ls
docker ps
查看所有的容器,把常驻内存并没有运行的 的那些搞出来
docker container ls -a
docker ps -a
交互式的运行
docker run -it centos
yum install -y vim
exit 退出之后就不会再运行了
退出的容器,删除容器
docker container rm ID
docker rm ID
快速清理掉所有 container
清理掉 所有常驻内存并没有运行的容器:
01.列出
docker container ls -aq // -q只列出ID
docker container ls -a |awk {‘print$1’}
02.清理掉
docekr rm $(docker container ls -aq )
03.验证
docker ps -a
#更加复杂的情况,想把退出的删除掉 ,运行的保留
01 列出exited 状态的container
docker container ls -f “status=exited”
02 删除掉
docker rm $(docker container ls -f “status=exited” -q)
---------------------3.5 构建自己的镜像--------------------------
01 # 把container 重新commit一个new image
基于已有的image ,在创建成为一个container 之后,
做了一些改变(安装了软件),想把这个新的改变打成新的image
docker container commit
docker commit
demo:
docker run -it centos // 基于Base image 交互式起一个container
yum -y install vim // 本来没有,安装一个
exit
docker container ls -a
docker commit ID/name dockerID/centos-vim
docker images
docker history ImageID(原来的)
docker history ImageID(新的)
02 #Build an image from a Dockerfile
docker image build
docker build
mkdir docker-centos-vim
cd docker-centos-vim
vim Dockerfile
FROM centos // 选定 Base image (只读的?怎么run!其实是先基于临时的)
RUN yum install -y vim // 在Base image 上运行安装命令
开始构建
docker build -t liuge36docker/centos-vim-new .
03 # 详解Dockerfile
介绍各个关键字
—FROM—
FROM scratch # 制作base image // 不依赖其他的image,原创一个
FROM centos # 使用base image // 基于已有的image 基础上
from最佳实践:尽量使用官方的image作为base image ,为了安全!
—LABEL—
定义image的metadata,像代码写注释一样
LABEL maintainer=“liuge36@163.com 作者”
LABEL version=“1.0”
LABEL description=“这里是image的描述信息”
label最佳实践:Metadata必不可少!
----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’
RUN最佳实践:为了美观,复杂的RUN 使用反斜线换行
避免无用分层,合并多条命令为一行,即一层。&&
----WORKDIR—
指定工作目录,就像cd /opt/spark/ 这种操作
WORKDIR /test #如果没有会自动创建test目录
WORDDIR demo # 进入到/test/demo
RUN pwd # 输出结果应该是/test/demo
WORKDIR最佳实践:尽量使用绝对路径,尽量不使用RUN cd 这种方式
----ADD 和 COPY ------
用于添加本地的文件到docker image内部
ADD : 可以添加和解压缩
ADD springboot.jar / # 把本地的文件添加到image里面
ADD test.tar.gz / #添加到根目录并解压缩
WORDDIR /root
ADD springboot.jar test/ # /root/test/springboot.jar
WORDDIR /root
COPY springboot.jar test/
ADD 和 COPY 最佳实践:大部分情况:COPY 优于ADD,但是ADD有解压的功能
添加远程的文件/目录请使用curl或wget下载
----ENV------
设定环境变量
ENV MYSQL_VERSION 5.6 # 设定常量,后面直接用
RUN apt-get install -y mysql-server= “${MYSQL_VERSION}”
&& rm -rf /var/lib/apt/lists/* # 引用常量,清理cache
ENV 最佳实践:尽量使用ENV,可以增加可维护性,就像maven使用version一样
–VOLUME 和 EXPOSE—
存储和网络
—CMD 和 ENTERPOINT ----
RUN : 执行命令并创建新的Image Layer(新的镜像层)
CMD: 设置容器启动后 默认执行 的命令和参数
ENTERPOINT: 设置容器 启动时 运行的命令
拓展:shell 格式 和 Exex格式
Shell 格式:
RUN apt-get install -y vim
CMD echo “hello docker~~”
ENTERPOINT echo “hello docker~~2”
Exec 格式:
RUN [“apt-get”,“install”,"-y",“vim”]
CMD ["/bin/echo",“hello docekr~~”]
ENTERPOINT ["/bin/echo",“hello docekr~~2”]
小案例:
Dockerfile1
FROM centos
ENV name DcoerLiuge # 设定一个常量
ENTERPOINT echo “hello $name”
// docker build -t liuge36docker/centos-enteypoint-shell .
// docker run liuge36docker/centos-enteypoint-shell
hello DcoerLiuge // 打印出来,OK。没有问题
Dockerfile2
FROM centos
ENV name DockerLiuge2
ENTERPOINT ["/bin/echo",“hello $name”]
// docker build -t liuge36docker/centos-enteypoint-exec .
// docker run liuge36docker/centos-enteypoint-exec
hello name 的值。并不是shell
修改如下:
Dockerfile3
FROM centos
ENV name DockerLiuge2
ENTERPOINT ["/bin/bash","-c",“echo hello $name”] // 指明是shell
你去build ,run 是可以打印 hello DockerLiuge2 的。
–CMD–
- 容器启动时,默认执行的命令
- 如果是 docker run 指定了其他命令,CMD命令会被忽略
- 如果定义了多个CMD ,只有最后一个会执行
例如:Dockerfile
FROM centos
ENV name DcoerLiuge
CMD echo “hello $name”
根据上面这个Dockerfile构建一个image之后,
docker run [image] // 输出结果是:hello DcoerLiuge
docker run -it [image] /bin/bash // 定义的CMD就会被忽略,不会被打印
–ENTERPOINT–
- 让容器以应用程序或者服务的形式运行
- 永不会被忽略,一定会执行
最佳实践:写一个shell脚本作为 entrypoint
COPY docker-entrypoint.sh /usr/local/bin/ # 拷贝一个shell脚本进去image
ENTERPOINT [“docker-entrypoint.sh”] # 作为一个启动脚本
EXPOSE 27017
CMD [“mongod”]
最佳实践:参考官方的Dockerfile 进行学习和修改
https://github.com/docker-library
比如 mysql5.7 Dockerfile:
https://github.com/docker-library/mysql/blob/master/5.7/Dockerfile
------------3.6 # Dockerfile 实战一 ------------
mkdir flask-demo
cd flask-demo
vim app.py
from flask import Flask
app = Flask(name)
@app.route(’/’)
def hello():
return “Hello Flask~~”
if name == ‘name’:
app.run()
直接运行:
pip install -y flask
python app.py
目的:把这个python app 打包成一个image,再运行起来
开始吧:
分析,运行这个app,需要python 和flask的环境依赖
第一步:准备app源代码
mkdir flask-hello-world
cd flask-demo-world
vim app.py
from flask import Flask
app = Flask(name)
@app.route(’/’)
def hello():
return “Hello Flask~~”
if name == ‘name’:
app.run()
第二步:编写Dockerfile
我们写Dockerfile就可以基于python Base image
vim Dockerfile
FROM python:2.7 # Base Image
LABEL maintainer=“liuge36liuge36@163.com”
RUN pip install -i https://pypi.douban.com/simple flask
COPY app.py /app/
WORDDIR /app # 设定工作目录
EXPOSE 5000 # 暴露5000端口
CMD ["python","app.py"]
:wq
第三步:根据Dockerfile Build Image
docker build -t liuge36docker/flask-hello-world .
出错:? 可以docker exec -it [image] /bin/bash
第四步:docker run -d liuge36docker/flask-hello-world
------------3.7 # image 的分发 ------------------
即:pull push 操作
基于dockerhub 。类似github
可以把自己build的image ,push上去
push 的前提 :要注册dockerhub
要想push,得先登录
[root@localhost ~]# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.
Username: liuge36docker
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@localhost ~]#
登录成功之后,就可以push了
#先删除带hello的container
docker rm $(docker ps -a |grep hello | awk {‘print$1’})
删除image 重新构建
docker rm [image]
docker build -t liuge36docker/hello-world .
开始push
[root@localhost hello-world]# docker push liuge36docker/hello-world:latest
The push refers to repository [docker.io/liuge36docker/hello-world]
d669ced3dff5: Pushed
latest: digest: sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1 size: 525
[root@localhost hello-world]#
刷新自己的dockerhub https://hub.docker.com/repositories
别人就可以拉取你的image了
[root@localhost hello-world]# docker rmi 2d73a16744c8
Untagged: liuge36docker/hello-world:latest
Untagged: liuge36docker/hello-world@sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1
Deleted: sha256:2d73a16744c88b95b064512543dea778aa051d931efa999d66a8bfd6e3838c24
Deleted: sha256:873c2d5ea1784b7ebcad04ee444d5b9f1c02b1d241018f5e644dab183c3b069c
Deleted: sha256:d669ced3dff508cec5444c056a30b34e2f98d75bc0cf9c062a31e0f25799ba08
[root@localhost hello-world]# docker images |grep hello
hello-world latest fce289e99eb9 13 months ago 1.84kB
[root@localhost hello-world]# docker pull liuge36docker/hello-world:latest
latest: Pulling from liuge36docker/hello-world
908ba8edad07: Pull complete
Digest: sha256:fc659b21569c4a05751438f9cf8910ad8a1267263843cdd835ac798a09a8c6b1
Status: Downloaded newer image for liuge36docker/hello-world:latest
docker.io/liuge36docker/hello-world:latest
[root@localhost hello-world]# docker images |grep hello
liuge36docker/hello-world latest 2d73a16744c8 5 minutes ago 8.44kB
hello-world latest fce289e99eb9 13 months ago 1.84kB
[root@localhost hello-world]#
√ √ √ √ √ √ √ 小技巧 : 将自己的github与docekrhub进行关联 √ √ √ √ √ √ √
√ √ √ √ √ √ √ 小技巧 : 根据官方提供的registry image搭建本地的registry,供公司或个人创建私有的 √ √ √ √ √ √ √
云服务器本机启动一台registry
$ docker run -d -p 5000:5000 --restart always --name registry registry:2
telnet 120.27.243.X 5000
本地往云服务器上面push
01 先build
docker build -t 120.27.243.X:5000/hello-world .
02 创建信任文件
vim /etc/docker/daemon.json
# 添加
{ "insecure-registries":["120.27.243.X:5000"] }
03 vim /lib/systemd/system/docker.service
#添加一行
EnvironmentFile=-/etc/docker/daemon.json
//ExecReload=/bin/kill -s HUP $MAINPID
04 systemctl restart docker
05 docker push 120.27.243.X:5000/hello-world
06 验证:120.27.243.X:5000/v2/_catalog
------------3.8 # 容器container的操作 ------------------
命令一:exec
01 bash进入运行中的容器:-it 交互式的进入
docker exec -it 容器ID/名称 /bin/bash
pwd
ps -ef |grep python
exit
02 python进入
docker exec -it 容器ID/名称 python
print “Hello Docker”
03 打印容器的IP地址
docker exec -it 容器ID/名称 ip a
命令二:stop start rm
docker stop 容器ID/名称
docker rm $(docker ps -aq) # 删除已退出的容器
指定名字
docker run -d --name=flask-demo liuge36docker/flask-hello-world
命令三:inspect
打印container详细信息
docker inspect 容器ID/名称
命令四:logs
运行日志
docker logs 容器ID/名称
------------3.9 # Dockerfile 实战二 ------------
CMD 结合 ENTERPOINT 一起使用
工具:命令行程序
build 一个linux的命令行工具
stress linux压力测试的工具
docker run -it ubuntu /bin/bash
/# apt-get update && apt-get install -y stress
which stress
stress --help
vm worker.默认占用256M内存
stress --vm 1
stress --vm 1 --verbose
创建一个worker
分配占用256M
释放进程
不断往复~~~
如何把stress打包成一个docker image
mkdir ubuntu-stress
cd ubuntu-stress
vim Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y stress
ENTERPOINT ["/usr/bin/stress"]
CMD []
Build Image
docekr build -t liuge36/ubuntu-stress .
Run
docker run -it liuge36/ubuntu-stress
加上参数:
docker run -it liuge36/ubuntu-stress --vm 1 --verbose
常驻内存的程序
命令行的工具
------------3.10 # 容器资源限制 ------------
CPU memory
在容器技术之前的虚拟化技术,虚拟机是可以做资源的 分配限定的
docker run --help
-m --memory
docker images
docker run --memory=200M liuge36/ubuntu-stress --vm 1 --verbose
–memory=200M 200+200swap一共400m
docker run --memory=200M liuge36/ubuntu-stress --vm 1 --verbose --vm-bytes 500M
-c --cpu-shares 相对权重,不是个数
docker run --cpu-shares=10 --name=test1 liuge36/ubuntu-stress --cpu 1
docker run --cpu-shares=5 --name=test2 liuge36/ubuntu-stress --cpu 1
有什么问题,欢迎留言讨论~~
更多文章:系统学习Docker 不迷路:https://blog.csdn.net/liuge36/category_7651616.html