Docker 的镜像和容器(系统学习Docker03)

写在前面

最为基础重要的两大概念:镜像和容器
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=“[email protected] 作者”
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 n a m e / / name // 无法打印,不能识别 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=“liuge36[email protected]
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

猜你喜欢

转载自blog.csdn.net/liuge36/article/details/104272597