Docker从入门到实战-深入探讨Image

如何给一个docker image的tag为none docker image list_容器

说白了,image就是由一层一层的layer组成的。

Image常见操作

(1)查看本地image列表

	docker images  
	docker image ls

(2) 获取远端镜像

	docker pull

(3) 删除镜像[注意此镜像如果正在使用,或者有关联的镜像,则需要先处理完]
 
	docker image rm imageid
	docker rmi -f imageid 强制删除镜像
	docker rmi -f $(docker image ls)     删除所有镜像

(4)运行镜像

	docker run image

(5) 发布镜像

	docker push

官方Image

https://github.com/docker-library

官方镜像制作的Dockerfile

https://github.com/docker-library/official-images/tree/master/library

Dockerfile镜像制作

指令说明

FROM

定制的镜像都是基于 FROM 的镜像,这里的 java:8 就是定制需要的基础镜像。

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。
ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
格式:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:

COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。

<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match

规则。例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到<目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 CMD 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
制作Dockerfile文件

做一个springboot应用的镜像,支持动态启动不同的jar

  • 下载Java镜像
docker pull java:8

基于java镜像自定义配置文件

# 创建文件

touch Dockerfile

#编辑文件

vi Dockerfile

Dockerfile内容如下

FROM java:8

ADD /springboot-docker-0.0.1-SNAPSHOT.jar //

ENTRYPOINT [“java”, “-jar”, “/springboot-docker-0.0.1-SNAPSHOT.jar”]

构建镜像

当前路径下上传springboot-docker-0.0.1-SNAPSHOT,该文件需要大家根据自己需要构建

[root@localhost docker-workspace]# ls

Dockerfile springboot-docker-0.0.1-SNAPSHOT.jar
开始构建

docker build -t springboot .

[root@localhost docker-workspace]# docker build -t springboot .

Sending build context to Docker daemon  17.06MB
Step 1/3 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/3 : ADD /springboot-docker-0.0.1-SNAPSHOT.jar //
 ---> e2a603ab9ecd
Step 3/3 : ENTRYPOINT ["java", "-jar", "/springboot-docker-0.0.1-SNAPSHOT.jar"]
 ---> Running in b514b318437b
Removing intermediate container b514b318437b
 ---> 4e291b60f844
Successfully built 4e291b60f844
Successfully tagged springboot:latest
查看镜像列表
[root@localhost docker-workspace]# docker images

REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
springboot   latest   d8de76659d3b   33 seconds ago   660MB
java          8         d23bdf5b1b1b   4 years ago     643MB
使用镜像运行容器

容器启动成功,结果如下:

docker run -d --name springboot-docker-c -p 10000:8080 springboot

# 容器命为springboot-docker-c

查看当前运行的容器

[root@localhost docker-workspace]# docker ps -l

CONTAINER ID   IMAGE       COMMAND                 CREATED         STATUS     
    PORTS                                         NAMES
acce1644be82   springboot   "java -jar /springbo…"   18 seconds ago   Up 15 
seconds   0.0.0.0:10000->8080/tcp, :::10000->8080/tcp   springboot-docker-c
查看log
# acce1644be82 为容器id

[root@bogon docker]# docker logs -f -t --tail 50 acce1644be82

2021-06-14T08:56:16.813287982Z 

2021-06-14T08:56:16.813347726Z   .   ____         _           __ _ _

2021-06-14T08:56:16.813354739Z /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
2021-06-14T08:56:16.813359929Z ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
2021-06-14T08:56:16.813364668Z \\/ ___)| |_)| | | | | || (_| | ) ) ) )

2021-06-14T08:56:16.813369157Z   ' |____| .__|_| |_|_| |_\__, | / / / /

2021-06-14T08:56:16.813373645Z  =========|_|==============|___/=/_/_/_/

2021-06-14T08:56:16.849581197Z :: Spring Boot ::               (v2.4.5)

2021-06-14T08:56:16.849634990Z 
访问SpringBoot 

镜像仓库 

发布镜像到docker hub 

前提 

2021-06-14T08:56:17.604626919Z 2021-06-14 08:56:17.565 INFO 1 --- [           
main] c.n.d.s.SpringbootDockerApplication     : Starting 
SpringbootDockerApplication v0.0.1-SNAPSHOT using Java 1.8.0_111 on acce1644be82 
with PID 1 (/springboot-docker-0.0.1-SNAPSHOT.jar started by root in /)

2021-06-14T08:56:17.604693166Z 2021-06-14 08:56:17.600 INFO 1 --- [           
main] c.n.d.s.SpringbootDockerApplication     : No active profile set, falling 
back to default profiles: default

2021-06-14T08:56:22.437778619Z 2021-06-14 08:56:22.435 INFO 1 --- [           
main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 

8080 (http)

2021-06-14T08:56:22.483275217Z 2021-06-14 08:56:22.478 INFO 1 --- [           
main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]

2021-06-14T08:56:22.483305895Z 2021-06-14 08:56:22.479 INFO 1 --- [           
main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache 
Tomcat/9.0.45]

2021-06-14T08:56:22.759259752Z 2021-06-14 08:56:22.752 INFO 1 --- [           
main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded 
WebApplicationContext

2021-06-14T08:56:22.759309427Z 2021-06-14 08:56:22.752 INFO 1 --- [           
main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: 
initialization completed in 4870 ms

2021-06-14T08:56:23.506626459Z 2021-06-14 08:56:23.498 INFO 1 --- [           
main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 

'applicationTaskExecutor'

2021-06-14T08:56:24.169153444Z 2021-06-14 08:56:24.164 INFO 1 --- [           
main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 
(http) with context path ''

2021-06-14T08:56:24.239297892Z 2021-06-14 08:56:24.231 INFO 1 --- [           
main] c.n.d.s.SpringbootDockerApplication     : Started 
SpringbootDockerApplication in 9.148 seconds (JVM running for 12.299)
访问SpringBoot

如何给一个docker image的tag为none docker image list_spring boot_02

镜像仓库

发布镜像到docker hub
前提
注册账号

docker hub官网注册 https://hub.docker.com/

客户端配置daemon.json

检查registry-mirrors和insecure-registries节点为缺省值,也就是[]
默认没有设置过就是缺省值

执行登陆
docker login

# 输入用户名和密码。
构建好自己的容器

比如springboot-docker

打包镜像

分为两种:

  1. 通过tag方式打包镜像
    语法 docker tag imageName:version userName/imageName:version

docker tag springboot-docker:latest kojon/springboot-docker:latest

  1. 通过commit方式打包镜像
    运行容器

docker run -d --name springboot-docker -p 8080:8080 springboot-docker
#此时通过docker ps -l 会得到一个容器id ef5f01dc4b9e
重新打包镜像

docker commit <容器名> <镜像名>

比如:

docker commit ef5f01dc4b9e kojon/springboot-docker

镜像命名规则
比如 kojon/springboot-docker 的镜像。

语法: userName/imageName

kojon是我的docker hub用户名,/前面要是你的用户名,才符合hub的规范

最后执行 push

docker push kojon/springboot-docker

阿里云docker hub

阿里云docker仓库

https://cr.console.aliyun.com/cn-hangzhou/instances/repositories

参考手册

https://cr.console.aliyun.com/repository/cn-hangzhou/dreamit/image-repo/details

(1)登录到阿里云docker仓库

sudo docker login --username=itcrazy2016@163.com
registry.cnhangzhou.aliyuncs.com
(2) 输入密码

(3) 创建命名空间,比如itcrazy2016

(4) 给image打tag sudo docker tag [ImageId]
registry.cn-hangzhou.aliyuncs.com/itcrazy2016/testdocker-image:v1.0
(5)推送镜像到docker阿里云仓库

sudo docker push
registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-dockerimage:v1.0
(6)别人下载,并且运行

docker pull
registry.cn-hangzhou.aliyuncs.com/itcrazy2016/test-docker-image:v1.0
docker run -d --name user01 -p 6661:8080
registry.cnhangzhou.aliyuncs.com/itcrazy2016/test-docker-image:v1.0

docker搭建私有镜像仓库

官方参考 https://docs.docker.com/registry/configuration/

环境说明
角色 系统类型 IP

服务端 	Centos 7  	192.168.56.185

客户端 	Centos 7   	192.168.56.186

客户端 	Windows 10 	192.168.119.47
私服服务器下载registry镜像

在服务端下载私服镜像

[root@localhost registry]# docker pull registry

Using default tag: latest
latest: Pulling from library/registry
ddad3d7c1e96: Pull complete 
6eda6749503f: Pull complete 
363ab70c2143: Pull complete 
5b94580856e6: Pull complete 
12008541203a: Pull complete 
Digest: sha256:bac2d7050dc4826516650267fe7dc6627e9e11ad653daca0641437abdf18df27
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest
运行registry镜像
docker run -itd -v /data/registry:/var/lib/registry --net=host --name kojon-registry registry:latest

run命令参数说明:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • –name=“nginx-lb”: 为容器指定一个名称;
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username=“ritchie”: 设置环境变量;
  • –env-file=[]: 从指定文件读入环境变量;
  • –cpuset=“0-2” or --cpuset=“0,1,2”: 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • –net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
    默认为bridge桥接,需要指定参数-p 来映射端口 参考-p参数
    如果使用–net=host 即让容器和宿主机共享同一网络,容器内部运行程序的端口不能和宿主 机有冲突
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;
  • –volume , -v: 绑定一个卷 将一个本地地址映射复制到docker内

示例如下:

# 运行镜像

[root@localhost registry]# docker run -itd -v /data/registry:/var/lib/registry -
p 5000:5000 --name kojon-registry registry:latest

47723102fe8d8ae35bce39744298f9dd916fa6515ed86805ceeaf693a4157410

查看日志:

[root@localhost registry]# docker logs -f -t --tail 500 
47723102fe8d8ae35bce39744298f9dd916fa6515ed86805ceeaf693a4157410
2021-05-19T08:47:05.128492112Z WARN[0000] No HTTP secret provided - generated 
random secret. This may cause problems with uploads if multiple registries are 
behind a load-balancer. To provide a shared secret, fill in http.secret in the 
configuration file or set the REGISTRY_HTTP_SECRET environment variable. 
go.version=go1.11.2 instance.id=aaec4b0e-266e-45f0-9876-e9713a879488 
service=registry version=v2.7.1
2021-05-19T08:47:05.128560572Z INFO[0000] redis not configured                   
      go.version=go1.11.2 instance.id=aaec4b0e-266e-45f0-9876-e9713a879488 
service=registry version=v2.7.1
2021-05-19T08:47:05.138087303Z INFO[0000] Starting upload purge in 25m0s         
      go.version=go1.11.2 instance.id=aaec4b0e-266e-45f0-9876-e9713a879488 
service=registry version=v2.7.1
2021-05-19T08:47:05.151680721Z INFO[0000] using inmemory blob descriptor cache   
      go.version=go1.11.2 instance.id=aaec4b0e-266e-45f0-9876-e9713a879488 
service=registry version=v2.7.1
2021-05-19T08:47:05.158031343Z INFO[0000] listening on [::]:5000                 
      go.version=go1.11.2 instance.id=aaec4b0e-266e-45f0-9876-e9713a879488 
service=registry version=v2.7.1
访问私服
  • 如果有防火墙,请先关闭或者添加TCP入口规则

防火墙命令

#查看防火墙运行状态

systemctl status firewalld

#关闭防火墙

service firewalld stop

  • 访问: http://192.168.56.185:5000/v2/_catalog

此时私服上还没有镜像,接下来配置好客户端就可以上传镜像了。

客户端配置daemon.json

官方配置参 https://docs.docker.com/engine/reference/commandline/dockerd/

默认缺省值是上传到docker hub上

{ “registry-mirrors”: [], “insecure-registries”: [], … other
 info}
 “registry-mirrors”: [
 “https://registry.hub.docker.com”], “insecure-registries”: [
 “registry.hub.docker.com”] … other info
}

需要修改为指定的仓库时,修改此处的insecure-registries的值

centos7客户端

创建daemon.json配置文件

创建并写入值

echo '{ "insecure-registries":["192.168.56.185:5000"] }' >  /etc/docker/daemon.json

重启docker服务

sudo systemctl daemon-reload
sudo systemctl restart docker
windows10客户端

打开docker desktop

设置通讯开关

如何给一个docker image的tag为none docker image list_spring boot_03


设置私服仓库地址,并重启

如何给一个docker image的tag为none docker image list_spring boot_04

客户端发布镜像

打tag

语法 docker tag imageName:version registry address/userName/imageName:version

docker tag springboot-docker:latest 192.168.56.185:5000/kojon/springbootdocker:latest

push 到仓库

语法 docker push registry-address/userName/imageName:version

docker push 192.168.56.185:5000/kojon/springboot-docker

docker命令是跨平台的,linux命令也如下:

PS C:\Users\OnlyC> docker images
REPOSITORY                                   TAG       IMAGE ID       CREATED   
    SIZE
springboot-docker                             latest   79f9b1219197   3 hours 
ago   643MB
java                                         latest   d23bdf5b1b1b   4 years 
ago   643MB
PS C:\Users\OnlyC> docker tag springboot-docker:latest 

192.168.56.185:5000/kojon/springboot-docker:latest
PS C:\Users\OnlyC> docker images
REPOSITORY                                   TAG       IMAGE ID       CREATED   
    SIZE

192.168.56.185:5000/kojon/springboot-docker   latest   79f9b1219197   3 hours 
ago   643MB
springboot-docker                             latest   79f9b1219197   3 hours 
ago   643MB
java                                         latest   d23bdf5b1b1b   4 years 
ago   643MB
PS C:\Users\OnlyC> docker push 192.168.56.185:5000/kojon/springboot-docker
Using default tag: latest
The push refers to repository [192.168.56.185:5000/kojon/springboot-docker]
35c20f26d188: Pushed
c3fe59dd9556: Pushed
6ed1a81ba5b6: Pushed
a3483ce177ce: Pushed
ce6c8756685b: Pushed
30339f20ced0: Pushed
0eb22bfb707d: Pushed
a2ae92ffcd29: Pushed
latest: digest: 
sha256:da8f846f6754fd60e2be2895b4816bdb43c745c38f390923f646dd831e4369e3 size: 

2000

windows上可以使用docker desktop 来push

如何给一个docker image的tag为none docker image list_java_05

搭建自己的Docker Harbor

(1)访问github上的harbor项目

https://github.com/goharbor/harbor

(2)下载版本,比如1.7.1

https://github.com/goharbor/harbor/releases

官方演示地址:https://demo.goharbor.io/harbor

账号admin 密码Harbor12345
(3) 找一台安装了docker-compose[这个后面的课程会讲解],上传并解压tar -zxvf xxx.tar.gz
(4) 进入到harbor目录
修改harbor.cfg文件,主要是ip地址的修改成当前机器的ip地址
同时也可以看到Harbor的密码,默认是Harbor12345
(5) 安装harbor,需要一些时间

sh install.sh
(6) 浏览器访问,比如192.168.56.185:8080,输入用户名和密码即可

深入探讨Container

既然container是由image运行起来的,那么是否可以理解为container和image有某种关系?

如何给一个docker image的tag为none docker image list_spring boot_06

理解 :其实可以理解为container只是基于image之后的layer而已,也就是可以通过docker run image 创建出一个container出来。

container到image

既然container是基于image之上的,想想是否能够由一个container反推出image呢?
肯定是可以的,比如通过docker run运行起一个container出来,这时候对container对一些修改,然后
再生成一个新的image,这时候image的由来就不仅仅只能通过Dockerfile咯。

(1) 拉取一个centos image docker pull centos (2) 根据centos镜像创建出一个container
 docker run -d -it --name my-centos centos (3) 进入my-centos容器中docker exec -it my-centos bash (4) 输入vim命令
bash: vim: command not found (5) 我们要做的是
 对该container进行修改,也就是安装一下vim命令,然后将其生成一个新的centos (6)
 在centos的container中安装vim yum install -y vim (7)
 退出容器,将其生成一个新的centos,名称为"vim-centos-image"语法 docker commit container-name newImage-name docker commit my-centos
 vim-centos-image (8) 查看镜像列表,并且基于"vim-centos-image"创建新的容器docker run -d -it --name my-vim-centos vim-centos-image (9)
 进入到my-vim-centos容器中,检查vim命令是否存在docker exec -it my-vim-centos bash

结论 :可以通过docker commit命令基于一个container重新生成一个image,但是一般得到image的方式不建议这么做,不然image怎么来的就全然不知咯。

container资源限制

如果不对container的资源做限制,它就会无限制地使用物理机的资源,这样显然是不合适的。

查看资源情况 :docker stats

内存限制
–memory Memory limit
如果不设置 --memory-swap,其大小和memory一样
docker run -d --memory 100M --name tomcat1 tomcat
CPU限制
–cpu-shares 权重
docker run -d --cpu-shares 10 --name tomcat2 tomcat
图形化资源监控

https://github.com/weaveworks/scope

sudo curl -L git.io/scope -o /usr/local/bin/scope
 sudo chmod a+x /usr/local/bin/scope
 scope launch 39.100.39.63
 #停止scope
 scope stop
 #同时监控两台机器,在两台机器中分别执行如下命令scope launch ip1 ip2
container常见操作
(1) 根据镜像创建容器
docker run -d --name -p 9090:8080 my-tomcat tomcat
 (2) 查看运行中的container
 docker ps
 (3) 查看所有的container[包含退出的] docker ps -a
 (4) 删除container
 docker rm containerid docker rm -f $(docker ps -a) 删除所有container
 (5)进入到一个container中
 docker exec -it container bash
 (6) 根据container生成image docker
 (7)查看某个container的日志docker logs container
 (8) 查看容器资源使用情况
 docker stats
 (9) 查看容器详情信息
 docker inspect container
 (10) 停止/启动容器
 docker stop/start container
底层技术支持

Container是一种轻量级的虚拟化技术,不用模拟硬件创建虚拟机。
Docker是基于Linux Kernel的Namespace、CGroups、UnionFileSystem等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。

Namespace:用来做隔离的,比如pid[进程]、net[网络]、mnt[挂载点]等
CGroups: Controller Groups用来做资源限制,比如内存和CPU等
Union file systems:用来做image和container分层