docker

一、什么是 Docker

1.1 官方定义

  • 最新官网首页

![image-lwgb.png](/upload/image-lwgb.png)

官方介绍

  • We have a complete container solution for you - no matter who you are and where you are on your containerization journey.

  • 翻译: 我们为你提供了一个完整的容器解决方案,不管你是谁,不管你在哪,你都可以开始容器的的旅程。

  • 官方定义: docker是一个容器技术。

1.2 Docker的起源

  • Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。

  • Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目 已经超过 5 万 7 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。

  • Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。

二、为什么是Docker

  • 在开发的时候,在本机测试环境可以跑,生产环境跑不起来

这里我们拿java Web应用程序举例,我们一个java Web应用程序涉及很多东西,比如jdk、tomcat、mysql等软件环境。当这些其中某一项版本不一致的时候,可能就会导致应用程序跑不起来这种情况。Docker则将程序以及使用软件环境直接打包在一起,无论在那个机器上保证了环境一致。

优势1: 一致的运行环境,更轻松的迁移

  • 服务器自己的程序挂了,结果发现是别人程序出了问题把内存吃完了,自己程序因为内存不够就挂了

这种也是一种比较常见的情况,如果你的程序重要性不是特别高的话,公司基本上不可能让你的程序独享一台服务器的,这时候你的服务器就会跟公司其他人的程序共享一台服务器,所以不可避免地就会受到其他程序的干扰,导致自己的程序出现问题。Docker就很好解决了环境隔离的问题,别人程序不会影响到自己的程序。

优势2:对进程进行封装隔离,容器与容器之间互不影响,更高效的利用系统资源

  • 公司要弄一个活动,可能会有大量的流量进来,公司需要再多部署几十台服务器

在没有Docker的情况下,要在几天内部署几十台服务器,这对运维来说是一件非常折磨人的事,而且每台服务器的环境还不一定一样,就会出现各种问题,最后部署地头皮发麻。用Docker的话,我只需要将程序打包到镜像,你要多少台服务,我就给力跑多少容器,极大地提高了部署效率。

优势3: 通过镜像复制N多个环境一致容器


三、Docker和虚拟机区别

> 关于Docker与虚拟机的区别,我在网上找到的一张图,非常直观形象地展示出来,话不多说,直接上图。

![image-emdb.png](/upload/image-emdb.png)

比较上面两张图,我们发现虚拟机是携带操作系统,本身很小的应用程序却因为携带了操作系统而变得非常大,很笨重。Docker是不携带操作系统的,所以Docker的应用就非常的轻巧。另外在调用宿主机的CPU、磁盘等等这些资源的时候,拿内存举例,虚拟机是利用Hypervisor去虚拟化内存,整个调用过程是虚拟内存->虚拟物理内存->真正物理内存,但是Docker是利用Docker Engine去调用宿主的的资源,这时候过程是虚拟内存->真正物理内存。


传统虚拟机

Docker容器

磁盘占用

几个GB到几十个GB左右

几十MB到几百MB左右

CPU内存占用

虚拟操作系统非常占用CPU和内存

Docker引擎占用极低

启动速度

(从开机到运行项目)几分钟

(从开启容器到运行项目)几秒

安装管理

需要专门的运维技术

安装、管理方便

应用部署

每次部署都费时费力

从第二次部署开始轻松简捷

耦合性

多个应用服务安装到一起,容易互相影响

每个应用服务一个容器,达成隔离

系统依赖

需求相同或相似的内核,目前推荐是Linux


四、Docker的安装

4.1 安装docker(centos7.x)

卸载原始docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

安装docker依赖

sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

设置docker的yum源

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

安装最新版的docker

sudo yum install docker-ce docker-ce-cli containerd.io

指定版本安装docker

yum list docker-ce --showduplicates | sort -r
sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
sudo yum install docker-ce-18.09.5-3.el7 docker-ce-cli-18.09.5-3.el7 containerd.io

启动docker

sudo systemctl enable docker
sudo systemctl start docker

关闭docker

sudo systemctl stop docker

测试docker安装

sudo docker run hello-world

4.2 bash安装(通用所有平台)

- 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装,另外可以通过 --mirror 选项使用国内源进行安装:执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。

curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

启动docker

sudo systemctl enable docker
sudo systemctl start docker

创建docker用户组

sudo groupadd docker

将当前用户加入docker组

sudo usermod -aG docker $USER

测试docker安装是否正确

docker run hello-world

五、Docker 的核心架构

![image-vqgn.png](/upload/image-vqgn.png)

  • 镜像: 一个镜像代表一个应用环境,他是一个只读的文件,如 mysql镜像,tomcat镜像,nginx镜像等

  • 容器: 镜像每次运行之后就是产生一个容器,就是正在运行的镜像,特点就是可读可写

  • 仓库:用来存放镜像的位置,类似于maven仓库,也是镜像下载和上传的位置

  • dockerFile:docker生成镜像配置文件,用来书写自定义镜像的一些配置

  • tar:一个对镜像打包的文件,日后可以还原成镜像


六、 Docker 配置阿里镜像加速服务

6.1 docker 运行流程

![image-bibw.png](/upload/image-bibw.png)

6.2 docker配置阿里云镜像加速

  • 访问阿里云登录自己账号查看docker镜像加速服务

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://lz2nib3q.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
  • 验证docker的镜像加速是否生效

[root@localhost ~]# docker info
		..........
    127.0.0.0/8
   Registry Mirrors:
    'https://lz2nib3q.mirror.aliyuncs.com/'
   Live Restore Enabled: false
   Product License: Community Engine

七、Docker的入门应用

7.1 docker 的第一个程序

docker run hello-world

[root@localhost ~]# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

八、常用命令

8.1 辅助命令

1.安装完成辅助命令

docker version	#查看docker的信息

docker info		#查看更详细的信息

docker --help	#帮助命令

# docker 执行命令格式:docker [option] command(具体命令)

8.2 Images 镜像命令

1.查看本机中所有镜像

docker images				# 列出本地所有镜像

docker images -a			#列出所有镜像(包含中间映像层)

docker images -q 			#只显示镜像id

2.搜索镜像

docker search [options] 镜像名 	#去dockerhub上查询当前镜像

# [options]可选参数
-s 指定值   						#列出收藏数不少于指定值的镜像
--no-trunc 						#显示完整的镜像信息

3.从仓库下载镜像

docker pull 镜像名[:TAG|@DIGEST]		#下载镜像

4.删除镜像

docker rmi 镜像名 		#删除镜像

docker rmi -f 镜像名		#强制删除

8.3 Contrainer 容器命令

1.运行容器

docker run 镜像名  # 镜像名新建并启动容器
				  # --name 别名为容器起一个名字
				  # -d 启动守护式容器(在后台启动容器)
				  # -p 映射端口号:原始端口号 指定端口号启动 (-p可以书写多个)

# 例:
docker run -it --name myTomcat -p 8888:8080 tomcat # 8888 是系统上外部端口,8080 是容器内服务监听的端口】
docker run -d --name myTomcat -P tomcat

2.查看运行的容器

docker ps 		# 列出所有正在运行的容器

docker ps -a 	# 正在运行的和历史运行过的容器

docker ps -q 	# 静默模式,只显示容器编号

3.停止|关闭|重启容器

docker start 容器名字或者容器id 		# 开启容器

docker restart 容器名或者容器id 		# 重启容器

docker stop 容器名或者容器id 			# 正常停止容器运行

docker kill 容器名或者容器id 			# 立即停止容器运行

4.删除容器

docker rm 容器id|name			 # 删除已经停止的容器

docker rm -f 容器id和容器名 		 # 强制删除(即时在运行的容器也能删除)

docker rm -f $(docker ps -aq) 	 # 删除所有容器

5.查看容器内进程

docker top 容器id或者容器名 		 # 查看容器内的进程

6.查看查看容器内部细节

docker inspect 容器id 			 # 查看容器内部细节

7.查看容器的运行日志

docker logs [OPTIONS] 容器id|name  	# 查看容器日志

#[OPTIONS]参数
-t 容器id或容器名   			# 加入时间戳

-f 容器id|name        		# 跟随最新的日志打印

--tail 数字					# 显示最后多少条

8.进入容器内部

docker exec [options] 容器id 容器内命令 #进入容器执行命令

#[options] 可选参数
-i						#以交互模式运行容器,通常与-t一起使用
-t						#分配一个伪终端  shell窗口   bash 
						
#进入容器的bash
docker exec -it 容器id|name bash   

#退出容器
exit 					

#指定以root 用户进入容器
docker exec -it --user root 容器id bash 

9.容器和宿主机之间复制文件

docker cp 文件|目录 容器id:容器路径           #将宿主机复制到容器内部

docker cp 容器id:容器内资源路径 宿主机目录路径  #将容器内资源拷贝到主机上 
#例
docker cp tomcat01:/usr/local/tomcat/RUNNING.txt ~/DPFS

10.数据卷(volum)实现与宿主机共享目录

docker run -v 宿主机的路径|任意别名:/容器内的路径 镜像名

注意:

1.如果是宿主机路径必须是绝对路径,宿主机目录会覆盖容器内目录内容

2.如果是别名则会在docker运行容器时自动在宿主机中创建一个目录,并将容器目录文件复制到宿主机中

11.打包镜像

docker save 镜像名 -o 名称.tar

12.载入镜像

docker load -i   名称.tar

13.容器打包成新的镜像

docker commit -m "描述信息" -a "作者信息" 容器id|name 打包的镜像名称:标签 

#例	  
docker commit -m "version-1" -a "guqingge" tomcat1 mytomcat

14.如何部署一个 web 项目 war 包项目

a. 将 test.war 上传到 linux 服务器

b. 通过 docker cp命令 将 test.war 复制到 tomcat 的 webapps 目录

c. 使用 ip 端口进行测试访问即可


九、docker的镜像原理

9.1 镜像是什么?

镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时所需的库、环境变量和配置文件。

9.2 为什么一个镜像会那么大?

镜像就是花卷

  • UnionFS(联合文件系统):

    Union文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。这种文件系统特性:就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录 。

9.3 Docker镜像原理

docker的镜像实际是由一层一层的文件系统组成。

  • bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。在docker镜像的最底层就是bootfs。这一层与Linux/Unix 系统是一样的,包含boot加载器(bootloader)和内核(kernel)。当boot加载完,后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时会卸载bootfs。

  • rootfs(root file system),在bootfs之上,包含的就是典型的linux系统中的/dev,/proc,/bin,/etc等标准的目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu/CentOS等等。

  • 我们平时安装进虚拟机的centos都有1到几个GB,为什么docker这里才200MB?对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令,工具,和程序库就可以了,因为底层直接使用Host的Kernal,自己只需要提供rootfs就行了。由此可见不同的linux发行版,他们的bootfs是一致的,rootfs会有差别。因此不同的发行版可以共用bootfs。

9.4 为什么docker镜像要采用这种分层结构呢?

最大的一个好处就是资源共享

  • 比如:有多个镜像都是从相同的base镜像构建而来的,那么宿主机只需在磁盘中保存一份base镜像。同时内存中也只需要加载一份base镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。Docker镜像都是只读的。当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为容器层,容器层之下都叫镜像层。


十、Docker安装常用服务

一、安装mysql

1.拉取mysql镜像到本地

docker pull mysql:tag  # tag不加默认最新版本

2.运行mysql服务

#暴露外部端口才能连接
docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d  mysql:tag  

3.进入mysql容器

docker exec -it 容器名称|容器id bash

4.外部查看mysql日志

docker logs 容器名称|容器id

5.使用自定义配置参数

docker run --name mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:tag

6.将容器数据位置与宿主机位置挂载保证数据安全

docker run --name mysql -v /root/mysql/data:/var/lib/mysql -v /root/mysql/conf.d:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:tag

7.通过其他客户端访问 如在window系统|macos系统使用客户端工具访问

8.将mysql数据库备份为sql文件

#导出全部数据
docker exec mysql|容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql  

#导出指定库数据
docker exec mysql sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql  
	
#导出指定库数据不要数据
docker exec mysql sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql  

9.执行sql文件到mysql中

docker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/xxx.sql

二、安装Redis

1.在docker hub搜索redis镜像

docker search redis

2.拉取redis镜像到本地

docker pull redis

3.启动redis服务运行容器

docker run --name redis -p 6379:6379 -d redis:tag      #暴露外部宿主机端口为6379进行连接

4.查看启动日志

docker logs -t -f 容器id|容器名称

5.进入容器内部查看

docker exec -it 容器id|名称 bash 

6.加载外部自定义配置启动redis容器

默认情况下redis官方镜像中没有redis.conf配置文件 需要去官网下载指定版本的配置文件

1. wget http://download.redis.io/releases/redis-5.0.8.tar.gz 下载官方安装包

2. 将官方安装包中配置文件进行复制到宿主机指定目录中如 /root/redis/redis.conf文件

3. 修改需要自定义的配置

bind 0.0.0.0 #开启远程权限
appenonly yes #开启aof持久化

4. 加载配置启动

docker run --name redis -v /root/redis:/usr/local/etc/redis -p 6379:6379 -d redis redis-server /usr/local/etc/redis/redis.conf  

7.将数据目录挂在到本地保证数据安全

docker run --name redis -v /root/redis/data:/data -v /root/redis/redis.conf:/usr/local/etc/redis/redis.conf -p 6379:6379 -d redis redis-server 					

三、安装Nginx

1.在docker hub搜索nginx

docker search nginx

2.拉取nginx镜像到本地

docker pull nginx

3.启动nginx容器

docker run -p 80:80 --name nginx01 -d nginx

4.进入容器

docker exec -it nginx01 /bin/bash

查找目录: whereis nginx

配置文件: /etc/nginx/nginx.conf

5.复制配置文件到宿主机

docker cp nginx01(容器id|容器名称):/etc/nginx/nginx.conf 宿主机名录

6.挂在nginx配置以及html到宿主机外部

docker run --name nginx02 -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf -v /root/nginx/html:/usr/share/nginx/html -p 80:80 -d nginx	

四、安装Tomcat

1.在docker hub搜索tomcat

docker search tomcat

2.下载tomcat镜像

docker pull tomcat

3.运行tomcat镜像

docker run -p 8080:8080 -d --name mytomcat tomcat

4.进入tomcat容器

docker exec -it mytomcat /bin/bash

5.将webapps目录挂载在外部

docker run -p 8080:8080 -v /root/webapps:/usr/local/tomcat/webapps -d --name mytomcat tomcat

五、安装MongoDB数据库

1.在docker hub搜索MongoDB

docker search MongoDb

2.下载mongo镜像

docker pull mongo

3.运行mongDB

docker run -d -p 27017:27017 --name mymongo mongo  #无须权限

4.查看mongo运行日志

docker logs -f mymongo 	

5.进入mongodb容器

docker exec -it mymongo /bin/bash

进去后可以直接执行mongo命令进行操作

6.常见具有权限的容器

docker run --name  mymongo  -p 27017:27017  -d mongo --auth

7.进入容器配置用户名密码

mongo
use admin 选择admin库
db.createUser({user:"root",pwd:"root",roles:[{role:'root',db:'admin'}]})   #创建用户,此用户创建成功,则后续操作都需要用户认证
exit

8.将mongoDB中数据目录映射到宿主机中

docker run -d -p 27017:27017 -v /root/mongo/data:/data/db --name mymongo mongo 

六、安装ElasticSearch

注意:调高JVM线程数限制数量

1.拉取镜像运行elasticsearch

# 1.dockerhub 拉取镜像
docker pull elasticsearch:6.4.2

# 2.查看docker镜像
docker image

# 3.运行docker镜像
docker run -p 9200:9200 -p 9300:9300 elasticsearch:6.4.2
  • 启动出现如下错误

2. 预先配置

1.在centos虚拟机中,修改配置sysctl.conf

vim /etc/sysctl.conf

2.加入如下配置

vm.max_map_count=262144 

3.启用配置

sysctl -p

注:这一步是为了防止启动容器时,报出如下错误:

bootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]

3.启动EleasticSearch容器

1、复制容器中data目录到宿主机中

docker cp 容器id:/usr/share/share/elasticsearch/data /root/es

2、运行ES容器 指定jvm内存大小并指定ik分词器位置

docker run -d --name es -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms128m -Xmx128m" -v /root/es/plugins:/usr/share/elasticsearch/plugins -v /root/es/data:/usr/share/elasticsearch/data elasticsearch:6.4.2

4.安装IK分词器

1、下载对应版本的IK分词器

wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.2/elasticsearch-analysis-ik-6.4.2.zip

2、解压到plugins文件夹中

yum install -y unzip
unzip -d ik elasticsearch-analysis-ik-6.4.2.zip

3、添加自定义扩展词和停用词

cd plugins/elasticsearch/config
vim IKAnalyzer.cfg.xml
<properties>
		<comment>IK Analyzer 扩展配置</comment>
		<!--用户可以在这里配置自己的扩展字典 -->
		<entry key="ext_dict">ext_dict.dic</entry>
		<!--用户可以在这里配置自己的扩展停止词字典-->
		<entry key="ext_stopwords">ext_stopwords.dic</entry>
	</properties>

4.在ik分词器目录下config目录中创建ext_dict.dic文件

编码一定要为UTF-8才能生效

vim ext_dict.dic 	#加入扩展词即可

5. 在ik分词器目录下config目录中创建ext_stopword.dic文件

vim ext_stopwords.dic #加入停用词即可

6.重启容器生效

docker restart 容器id

7.将此容器提交成为一个新的镜像

docker commit -a="xiaochen" -m="es with IKAnalyzer" 容器id xiaochen/elasticsearch:6.4.2

5. 安装Kibana

1.下载kibana镜像到本地

docker pull kibana:6.4.2

2.启动kibana容器

docker run -d --name kibana -e ELASTICSEARCH_URL=http://10.15.0.3:9200 -p 5601:5601 kibana:6.4.2

7版本以后是

docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://10.15.0.3:9200 -p 5601:5601 kibana:6.4.2

十一、Docker中出现如下错误解决方案

[root@localhost ~]# docker search mysql 或者 docker pull 这些命令无法使用
Error response from daemon: Get https://index.docker.io/v1/search?q=mysql&n=25: x509: certificate has expired or is not yet valid

这个错误的原因在于是系统的时间和docker hub时间不一致,需要做系统时间与网络时间同步

1.安装时间同步

sudo yum -y install ntp ntpdate

2.同步时间

sudo ntpdate cn.pool.ntp.org

3.查看本机时间

date

4.重新测试


十二、Dockerfile

一、什么是Dockerfile

Dockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本。主要作用是用来构建docker镜像的构建文件

通过架构图可以看出通过DockerFile可以直接构建镜像

二、Dockerfile解析过程

三、Dockerfile的保留命令

[官方说明](https://docs.docker.com/engine/reference/builder/)

保留字

作用

FROM

当前镜像是基于哪个镜像的 第一个指令必须是FROM

MAINTAINER

镜像维护者的姓名和邮箱地址

RUN

构建镜像时需要运行的指令

EXPOSE

当前容器对外暴露出的端口号

WORKDIR

指定在创建容器后,终端默认登录进来的工作目录,一个落脚点

ENV

用来在构建镜像过程中设置环境变量

ADD

将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar包

COPY

类似于ADD,拷贝文件和目录到镜像中 将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

VOLUME

容器数据卷,用于数据保存和持久化工作

CMD

指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

ENTRYPOINT

指定一个容器启动时要运行的命令 ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数

1.FROM 命令

基于那个镜像进行构建新的镜像,在构建时会自动从docker hub拉取base镜像 必须作为Dockerfile的第一个指令出现

语法:

FROM  <image>
FROM  <image>[:<tag>]     #使用版本不写为latest
FROM  <image>[@<digest>]  #使用摘要

2.MAINTAINER 命令

镜像维护者的姓名和邮箱地址[废弃]

语法:

MAINTAINER <name>

3.RUN 命令

RUN指令将在当前映像之上的新层中执行任何命令并提交结果。生成的提交映像将用于Dockerfile中的下一步

语法:

RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN echo hello
 ​
RUN ["executable", "param1", "param2"] (exec form)
RUN ["/bin/bash", "-c", "echo hello"]

4.EXPOSE 命令

用来指定构建的镜像在运行为容器时对外暴露的端口

语法:

EXPOSE 80/tcp  #如果没有显示指定则默认暴露都是tcp
EXPOSE 80/udp

5.CMD 命令

用来为启动的容器指定执行的命令,在Dockerfile中只能有一条CMD指令。如果列出多个命令,则只有最后一个命令才会生效。

注意: Dockerfile中只能有一条CMD指令。如果列出多个命令,则只有最后一个命令才会生效。

语法:

CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)

6.WORKDIR 命令

用来为Dockerfile中的任何RUN、CMD、ENTRYPOINT、COPY和ADD指令设置工作目录。如果WORKDIR不存在,即使它没有在任何后续Dockerfile指令中使用,它也将被创建。

语法:

WORKDIR /path/to/workdir
 ​
WORKDIR /a
WORKDIR b
WORKDIR c

注意:WORKDIR指令可以在Dockerfile中多次使用。如果提供了相对路径,则该路径将与先前WORKDIR指令的路径相对

7.ENV 命令

用来为构建镜像设置环境变量。这个值将出现在构建阶段中所有后续指令的环境中。

语法:

ENV <key> <value>
ENV <key>=<value> ...

8.ADD 命令

用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中。

语法:

ADD hom* /mydir/       #通配符添加多个文件
ADD hom?.txt /mydir/   #通配符添加
ADD test.txt relativeDir/  #可以指定相对路径
ADD test.txt /absoluteDir/ #也可以指定绝对路径
ADD url 

9.COPY 命令

用来将context目录中指定文件复制到镜像的指定目录中

语法:

COPY src dest
COPY ["<src>",... "<dest>"]

10.VOLUME 命令

用来定义容器运行时可以挂在到宿主机的目录

语法:

VOLUME ["/data"]

11.ENTRYPOINT命令

用来指定容器启动时执行命令和CMD类似

语法:

["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

ENTRYPOINT指令,往往用于设置容器启动后的第一个命令,这对一个容器来说往往是固定的。 CMD指令,往往用于设置容器启动的第一个命令的默认参数,这对一个容器来说可以是变化的。


十三、Dockerfile构建springboot项目部署

1.准备springboot可运行项目

2.将可运行项目放入linux虚拟机中

3.编写Dockerfile

FROM openjdk:8
WORKDIR /ems
ADD ems.jar /ems
EXPOSE 8989
ENTRYPOINT ["java","-jar"]
CMD ["ems.jar"]

4.构建镜像

 [root@localhost ems]# docker build -t ems .

5.运行镜像

 [root@localhost ems]# docker run -p 8989:8989 ems

6.访问项目

 http://10.15.0.8:8989/ems/login.html


10.高级网络配置

一、说明

当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。

同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口。比如典型的 172.17.42.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。

当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。

二、查看网络信息

docker network ls

三、创建一个网桥

docker network create -d bridge 网桥名称

四、删除一个网桥

docker network rm 网桥名称

五、容器之前使用网络通信

1.查询当前网络配置

docker network ls
 NETWORK ID          NAME                DRIVER              SCOPE
 8e424e5936b7        bridge              bridge              local
 17d974db02da        docker_gwbridge     bridge              local
 d6c326e433f7        host                host                local

2.创建桥接网络

docker network create -d bridge info
 [root@centos ~]# docker network create -d bridge info
 6e4aaebff79b1df43a064e0e8fdab08f52d64ce34db78dd5184ce7aaaf550a2f
 [root@centos ~]# docker network ls
 NETWORK ID          NAME                DRIVER              SCOPE
 8e424e5936b7        bridge              bridge              local
 17d974db02da        docker_gwbridge     bridge              local
 d6c326e433f7        host                host                local
 6e4aaebff79b        info                bridge              local

3.启动容器指定使用网桥

docker run -d -p 8890:80 --name nginx001 --network info nginx 
docker run -d -p 8891:80 --name nginx002 --network info nginx 

注意:一旦指定网桥后--name指定名字就是主机名,多个容器指定在同一个网桥时,可以在任意一个容器中使用主机名与容器进行互通

 [root@centos ~]# docker run -d -p 8890:80 --name nginx001 --network info nginx 
 c315bcc94e9ddaa36eb6c6f16ca51592b1ac8bf1ecfe9d8f01d892f3f10825fe
 [root@centos ~]# docker run -d -p 8891:80 --name nginx002 --network info nginx
 f8682db35dd7fb4395f90edb38df7cad71bbfaba71b6a4c6e2a3a525cb73c2a5
 [root@centos ~]# docker ps
 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
 f8682db35dd7        nginx               "/docker-entrypoint.…"   3 seconds ago       Up 2 seconds        0.0.0.0:8891->80/tcp   nginx002
 c315bcc94e9d        nginx               "/docker-entrypoint.…"   7 minutes ago       Up 7 minutes        0.0.0.0:8890->80/tcp   nginx001
 b63169d43792        mysql:5.7.19        "docker-entrypoint.s…"   7 minutes ago       Up 7 minutes        3306/tcp               mysql_mysql.1.s75qe5kkpwwttyf0wrjvd2cda
 [root@centos ~]# docker exec -it f8682db35dd7 /bin/bash
 root@f8682db35dd7:/# curl http://nginx001
 <!DOCTYPE html>
 <html>
 <head>
 <title>Welcome to nginx!</title>
 .....

十四、高级数据卷配置

一、说明

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用

  • 数据卷 的修改会立马生效

  • 数据卷 的更新,不会影响镜像

  • 数据卷 默认会一直存在,即使容器被删除

注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。

二、创建数据卷

docker volume create my-vol

三、查看数据卷

docker volume inspect my-vol   


[
    {
        "CreatedAt": "2020-11-25T11:43:56+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]    

四、挂载数据卷

docker run -d -P --name web  -v my-vol:/usr/share/nginx/html  nginx
docker inspect web


"Mounts": [
   {
      "Type": "volume",
      "Name": "my-vol",
      "Source": "/var/lib/docker/volumes/my-vol/_data",
      "Destination": "/usr/share/nginx/html",
      "Driver": "local",
      "Mode": "z",
      "RW": true,
      "Propagation": ""
    }
],

五、删除数据卷

 docker volume rm my-vol

十五、Docker Compose

一、简介

Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。从功能上看,跟 OpenStack 中的 Heat 十分类似。

其代码目前在 https://github.com/docker/compose 上开源。

Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。

通过第一部分中的介绍,我们知道使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。

Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

Compose 中有两个重要的概念:

  • 服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。

  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。

二、安装与卸载

1.linux

在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。例如,在 Linux 64 位系统上直接下载对应的二进制包。

sudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

2.macos、window

Compose 可以通过 Python 的包管理工具 pip 进行安装,也可以直接下载编译好的二进制文件使用,甚至能够直接在 Docker 容器中运行。Docker Desktop for Mac/Windows 自带 docker-compose 二进制文件,安装 Docker 之后可以直接使用

3.bash命令补全

curl -L https://raw.githubusercontent.com/docker/compose/1.25.5/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

4.卸载

如果是二进制包方式安装的,删除二进制文件即可。

sudo rm /usr/local/bin/docker-compose

5.测试安装成功

docker-compose --version
#docker-compose version 1.25.5, build 4667896b

三、docker compose使用

1.相关概念

首先介绍几个术语。

  • 服务 (service):一个应用容器,实际上可以运行多个相同镜像的实例。

  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元。∂一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。

2.场景

最常见的项目是 web 网站,该项目应该包含 web 应用和缓存。

  • springboot应用

  • mysql服务

  • redis服务

  • elasticsearch服务

  • .......

3.docker-compose模板

参考文档:https://docker_practice.gitee.io/zh-cn/compose/compose_file.html

 version: "3.0"
 services:
   mysqldb:
     image: mysql:5.7.19
     container_name: mysql
     ports:
       - "3306:3306"
     volumes:
       - /root/mysql/conf:/etc/mysql/conf.d
       - /root/mysql/logs:/logs
       - /root/mysql/data:/var/lib/mysql
     environment:
       MYSQL_ROOT_PASSWORD: root
     networks:
       - ems
     depends_on:
       - redis
 ​
   redis:
     image: redis:4.0.14
     container_name: redis
     ports:
       - "6379:6379"
     networks:
       - ems
     volumes:
       - /root/redis/data:/data
     command: redis-server
     
 networks:
   ems:

4.通过docker-compose运行一组容器

参考文档:https://docker_practice.gitee.io/zh-cn/compose/commands.html

前台启动一组服务

docker-compose up    #前台启动一组服务

后台启动一组服务

docker-compose up -d   #后台启动一组服务

四、docker-compose 模板文件

模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的。

默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。

 version: "3"
 ​
 services:
   webapp:
     image: examples/web
     ports:
       - "80:80"
     volumes:
       - "/data"

注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。

如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中重复设置。

下面分别介绍各个指令的用法。

build

指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。

 version: '3'
 services:
 ​
   webapp:
     build: ./dir

你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径。

使用 dockerfile 指令指定 Dockerfile 文件名。

使用 arg 指令指定构建镜像时的变量。

 version: '3'
 services:
 ​
   webapp:
     build:
       context: ./dir
       dockerfile: Dockerfile-alternate
       args:
         buildno: 1

command

覆盖容器启动后默认执行的命令。

 command: echo "hello world"

container_name

指定容器名称。默认将会使用 项目名称_服务名称_序号 这样的格式。

 container_name: docker-web-container

注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。

depends_on

解决容器的依赖、启动先后的问题。以下例子中会先启动 redis db 再启动 web

 version: '3'
 ​
 services:
   web:
     build: .
     depends_on:
       - db
       - redis
 ​
   redis:
     image: redis
 ​
   db:
     image: postgres

注意:web 服务不会等待 redis db 「完全启动」之后才启动。

env_file

从文件中获取环境变量,可以为单独的文件路径或列表。

如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。

如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准。

 env_file: .env
 ​
 env_file:
   - ./common.env
   - ./apps/web.env
   - /opt/secrets.env

环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

 # common.env: Set development environment
 PROG_ENV=development

environment

设置环境变量。你可以使用数组或字典两种格式。

只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据。

 environment:
   RACK_ENV: development
   SESSION_SECRET:
 ​
 environment:
   - RACK_ENV=development
   - SESSION_SECRET

如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括

 y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF

healthcheck

通过命令检查容器是否健康运行。

 healthcheck:
   test: ["CMD", "curl", "-f", "http://localhost"]
   interval: 1m30s
   timeout: 10s
   retries: 3

image

指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。

 image: ubuntu
 image: orchardup/postgresql
 image: a4bc65fd

networks

配置容器连接的网络。

 version: "3"
 services:
 ​
   some-service:
     networks:
      - some-network
      - other-network
 ​
 networks:
   some-network:
   other-network:

ports

暴露端口信息。

使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

 ports:
  - "3000"
  - "8000:8000"
  - "49100:22"
  - "127.0.0.1:8001:8001"

注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。

sysctls

配置容器内核参数。

 sysctls:
   net.core.somaxconn: 1024
   net.ipv4.tcp_syncookies: 0
 ​
 sysctls:
   - net.core.somaxconn=1024
   - net.ipv4.tcp_syncookies=0

ulimits

指定容器的 ulimits 限制值。

例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。

   ulimits:
     nproc: 65535
     nofile:
       soft: 20000
       hard: 40000

volumes

数据卷所挂载路径设置。可以设置为宿主机路径(HOST:CONTAINER)或者数据卷名称(VOLUME:CONTAINER),并且可以设置访问模式 (HOST:CONTAINER:ro)。

该指令中路径支持相对路径。

 volumes:
  - /var/lib/mysql
  - cache/:/tmp/cache
  - ~/configs:/etc/configs/:ro

如果路径为数据卷名称,必须在文件中配置数据卷。

 version: "3"
 ​
 services:
   my_src:
     image: mysql:8.0
     volumes:
       - mysql_data:/var/lib/mysql
 ​
 volumes:
   mysql_data:

十六、docker-compose 常用命令

一、命令对象与格式

对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响。

执行 docker-compose [COMMAND] --help 或者 docker-compose help [COMMAND] 可以查看具体某个命令的使用格式。

docker-compose 命令的基本的使用格式是

 docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

二、命令选项

  • -f, --file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。

  • -p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。

  • --x-networking 使用 Docker 的可拔插网络后端特性

  • --x-network-driver DRIVER 指定网络后端的驱动,默认为 bridge

  • --verbose 输出更多调试信息。

  • -v, --version 打印版本并退出。

三、命令使用说明

up

格式为 docker-compose up [options] [SERVICE...]

  • 该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。

  • 链接的服务都将会被自动启动,除非已经处于运行状态。

  • 可以说,大部分时候都可以直接通过该命令来启动一个项目。

  • 默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。

  • 当通过 Ctrl-C 停止命令时,所有容器将会停止。

  • 如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。

  • 默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容

down

  • 此命令将会停止 up 命令所启动的容器,并移除网络

exec

  • 进入指定的容器。

ps

格式为 docker-compose ps [options] [SERVICE...]

列出项目中目前的所有容器。

选项:

  • -q 只打印容器的 ID 信息。

restart

格式为 docker-compose restart [options] [SERVICE...]

重启项目中的服务。

选项:

  • -t, --timeout TIMEOUT 指定重启前停止容器的超时(默认为 10 秒)。

rm

格式为 docker-compose rm [options] [SERVICE...]

删除所有(停止状态的)服务容器。推荐先执行 docker-compose stop 命令来停止容器。

选项:

  • -f, --force 强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项。

  • -v 删除容器所挂载的数据卷。

start

格式为 docker-compose start [SERVICE...]

启动已经存在的服务容器。

stop

格式为 docker-compose stop [options] [SERVICE...]

停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。

选项:

  • -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。

top

查看各个服务容器内运行的进程。

unpause

格式为 docker-compose unpause [SERVICE...]

恢复处于暂停状态中的服务。


十七、docker可视化工具

一、安装Portainer

[官方安装说明](https://www.portainer.io/installation/)

docker pull  portainer/portainer
 ​
docker volume create portainer_data

docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

docker ps 
#CONTAINER ID        IMAGE                 COMMAND             #CREATED             STATUS              PORTS                       #                     NAMES
# 20db26b67b79        portainer/portainer   "/portainer"        5 #seconds ago       Up 4 seconds        0.0.0.0:8000->8000/tcp, #0.0.0.0:9000->9000/tcp   portainer

二、登录和使用Portainer

用浏览器访问:http://localhost:9000



十八、小记

一、MacOS解决Docker启动Tomcat容器,访问404问题

参考https://blog.csdn.net/weixin_44311939/article/details/104675176

1.使用docker命令启动Tomcat容器

docker run -d -p 8888:8080 tomcat

2.查看已经启动的容器

docker ps

使用映射端口8888访问Tomcat失败

使用如下命名进入docker容器中Tomcat的目录

docker exec -it 容器id /bin/ bash

3.查看当前文件夹内的所有文件

ls -l

4.进入webapps文件夹下

cd webapps

显示total 0,问题就出在这里,webapps文件夹下没有东西

返回上一级目录

cd ..

5.删除webapps文件夹

-r是级联删除,-f是强制删除,不然文件夹是删不掉的

rm -rf webapps

6.将webapps.dist文件夹下的内容复制到给webapps文件夹,-r 递归复制

cp -r webapps.dist webapps

此时再访问Tomcat,成功


二、容器数据卷机制

数据卷 Data Volume

1.作用

用来实现容器中数据和宿主机中数据进行映射的(同步的)

2.注意

数据卷使用必须在容器首次启动时设置

3.使用

docker run -d -p 8081:8080 --name tomcat01 -v tomcat:8.0

1.使用绝对路径设置数据卷

docker run -v 宿主机绝对路径:容器内路径:ro -v 宿主机绝对路径:容器内路径:ro    ...

ro: readonly 只读,如果设置数据卷时指定 ro,代表日后容器内路径是只读的。

就是容器指定了ro,只能宿主机的目录改变影响到容器中目录,容器中的目录是只读的无法进行写操作。如果不设置 ro 的话宿主机目录改变可以影响容器目录,容器目录改变也可以影响宿主机。

注意:这种方式会将容器路径的原始内容全部清空,始终以宿主机路径为主

2. 使用别名方式设置数据卷

docker run -v aa:/usr/local/tomcat/webapps ...

aa是什么

  1. 1. aa 代表 docker 数据卷中别名 注意:这个别名如果存在,docker 直接使用,aa 不存在自动创建

  2. 使用别名方式保留容器路径原始内容,前提别名对应路径不能存在内容

例:

docker -d -p 8082:8080 --name tomcat03 -v aaa:/usr/local/tomcat/webapps tomcat:8.0

三、docker三个核心概念

1.仓库:repository

作用

docker 官方维护一个仓库,用来集中存储镜像

2.镜像:Image

作用

一个镜像代表一个软件服务

特点

只读

容器:container

作用

镜像每运行一次形成一个容器,运行的容器代表一个正在运行软件服务

特点

可读可写


四、容器打包成一个新的镜像

为什么要将容器打包成一个新的镜像

原因:容器可读可写 ,基于这个特性我们就可以对容器进行自己深度定制,将修改的容器打包成一个新的镜像,日后基于这个镜像运行成容器存在原始定制特性。

如何将容器打包成一个新的镜像

docker commit -m "描述信息" -a "修改者" 容器id|name 镜像名:版本

五、镜像备份和恢复

镜像备份

docker save 镜像名 -o 路径/名称.tar

-o 表示 out,输出,名称建议涵盖镜像名称和版本(镜像名-版本)

例:

docker save tomcat8.0 -o ~/DPFD/docker/tomcat-8.0.tar

恢复镜像

docker load -i 名称.tar 

-i 表示image,镜像,装载一个镜像

例:

docker load -i tomcat-8.0.tar

六、镜像构成原理

一、Image 镜像为什么这么大?

tomcat: 10M

Image: 356M

解释:容器独立操作系统(精简 linux 操作系统+软件服务)===>镜像运行 ===>镜像(操作系统库+软件文件)

二、镜像原理

镜像是什么

镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时所需的库、环境变量和配置文件。

docker 官方使用:UnionFS(联合文件系统),比如一个 tomcat 镜像,包含了操作系统核心库和 jdk 运行环境,还有 tomcat 依赖+tomcat 软件服务,要维护 tomcat 不同版本的话,其实操作系统核心库和 jdk 运行环境可以是一样的,只维护 tomcat 依赖和 tomcat 软件服务的版本即可。docker 使用 UnionFS (联合文件系统),将这些公共的部分抽离出来,单独做成一个镜像。BaseImage操作系统+jdk 运行环境,我们运行镜像的时候它是一层一层加载的,它会先去加载最底层的这个 BaseImage,一层层的叠加。站在tomcat 的角度看,我们需要操作系统和 JDK 运行环境。但是日后我们要运行像 nacos,是不需要 JDK 的,又怎么办呢?所以这个 BaseImage 还可以再拆分,拆分成 BaseImage 就是一个操作系统的镜像,JDK 也单独拆分成一个镜像,可能还会在操作系统镜像上再去做一个比如说像 C语言的一些库的镜像,满足 C 语言的相关服务使用。在这些镜像之上我们可以加我们的 tomcat 等服务,如果不需要 JDK 环境的,我们直接可以基于 BaseImage 操作系统的镜像上加我们的相关服务即可。其实底层做的是更细的,有些软件可以运行在不同的 linux 发现版本里面,不同的 linux 发行版,又可以将这个 BaseImage 拆分分层的更细。如开机引导 boot/ , /home , /etc ,一层一层的拆分,您可以组装成你需要的版本

UnionFS:联合文件系统 ,叠加文件系统

原理

就是一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录 。


七、docker启动各种服务

1、docker启动mysql

建议:使用任何容器参考 dockerhub 官方网站 + 搜索引擎(百度 google)

1.下载 mysql 镜像

a.访问 docker hub

b.确定版本 5.x (行业流行版本) ---> 8.x(最新版本,引擎更加快 特性)

2.下载

docker pull mysql:5.6 

macM1芯片:

docker pull mysql/mysql-server:5.6 

M1芯片是arm64架构,也称作aarch64架构,只能运行arm64/aarch64架构的程序,只有 mysql 官方提供的 mysql/mysql-server 有,我们可以使用这个

3.运行mysql

a.启动 mysql,开放端口映射(3306)指定 root 用户密码才行 -e(environment环境)

docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=shixiang mysql/mysql-server:5.6

b.启动 mysql,开启端口映射(3306)指定 root 用户密码 -e MYSQL_ROOT_PASSWORD=xx 后台运行-d 指定名称 --name

c.启动 mysql,开启端口映射(3306)指定 root 用户密码 -e MYSQL_ROOT_PASSWORD=xx 后台运行-d 指定名称 --name 总是运行--restart=always 这样 docker 引擎重启mysql 服务也会重启

如:

docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=shixiang -d --name mysql02 --restart=always mysql/mysql-server:5.6

d.启动 mysql,端口(3306)root用户密码 -e MYSQL_ROOT_PASSWORD=xx 后台运行-d 指定名称 --name 总是运行--restart=always 数据卷持久化数据到宿主机

docker run -p 3307:3306 -e MYSQL_ROOT_PASSWORD=shixiang -d --name mysql02 --restart=always -v ~/DPFS/data:/var/lib/mysql mysql/mysql-server:latest

4.进入容器内部

docker exec -it 容器id bash

[docker exec -it --user root 容器id bash]指定以 root 用户进入容器

5.docker 运行 mysql 容器数据备份

1.在使用 mysql 容器时数据卷虽然能备份数据

注意:数据卷将数据库底层文件系统进行的备份 不利于数据和备份,推荐使用 sql 文件形式备份数据

2.如何在 mysql 中导出 sql 文件来备份数据
2.1利用 mysql 官方命令 mysqldump

备份全部数据:

docker exec (mysql)容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql  

备份指定库中数据:

docker exec mysql容器id sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/ems-databases.sql

备份指定库中结构不要数据:

docker exec mysql容器id sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/ems.sql
2.2使用 navicat 提供数据备份

直接在对应库中选择备份的表即可,导出即可

6.mysql远程授权问题无法连接解决

1.查询加密规则

进入容器内部连接上mysql

use mysql;
select host,user,plugin from user;
2.进行授权远程连接
GRANT ALL ON *.* TO 'root'@'%';

注意mysql 8.0跟之前的授权方式不同

3.刷新权限
flush privileges;

此时,还不能远程访问,因为Navicat只支持旧版本的加密,需要更改mysql的加密规则

4.查询加密规则
select host,user,plugin from user;

如果是 caching_sha2_password ,需要更改为mysql_native_password

5.更改加密规则

ALTER USER '用户名'@'访问主机' IDENTIFIED WITH mysql_native_password BY '密码';

-- 例
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'shixiang';
6.当使用 grant all privileges on . to '用户名'@'访问主机' identified by '密码'; 时出现如下报错:
......near 'identified by '密码'' at line 1
原因:

因为新版本的mysql将创建账户和赋予权限两个过程拆分开了,原来的语法不支持了

解决办法:

将这两步分开操作

1.创建账户:

create user '用户名'@'访问主机' identified by '密码';

# 例
create user 'root'@'192.168.1.10' identified by 'shixiang';

2.赋予权限:

grant 权限列表 on 数据库 to '用户名'@'访问主机' ; --(修改权限时在后面加with grant option)

grant all privileges on *.* to 'root'@'%' with grant option ;

如果出现:

ERROR 1410 (42000): You are not allowed to create a user with GRANT

原因:

当前user表中没有root - %记录; 可以更新root - localhost 为 root - %

update user set host = '%' where user = 'root';

然后再次赋权

3.刷新权限

flush privileges;

2、docker运行redis服务

1.去 docker hub 确定版本

docker search redis

2.通过 docker 下载 redis

docker pull redis:5.0.12

3.运行 redis

1.启动 redis 映射端口(6379)
docker run -p 6379:6379 redis:5.0.12 
2.启动 redis 映射端口(6379) 后台启动-d 指定名称--name 总是启动--restart=always
docker run -p 6379:6379 -d --name -restart=always redis:5.0.12

redis 支持内存数据持久化:

1. rdb持久化 :快照 Redis 服务器将某一时刻数据以快照文件形式写入到磁盘

2. aof持久化 :redis 服务器将所有 redis 客户端的写操作以命令方式记录到日志文件中 AOF更加安全

3.docker 运行 redis 如何开启持久化
docker run --name redis03 -d -p 6379:6379 --restart=always redis:5.0.12 redis-server --appendonly yes

注意:只要开启了持久化,将持久化文件生成容器中 /data/目录中

4.docker 启动 redis 开放端口 后台启动 指定名称 总是启动 开启持久化 映射数据文件外部
docker run -p 6379:6379 -d --name redis02 --restart=always -v ~/DPFS/data/redis-data:/data redis:5.0.12 redis-server --appendonly yes

4.如何自定义配置文件启动 redis

1.如何获取 redis 配置文件

第一种方式:下载对应版本找到配置文件 进行修改 使用完整配置文件启动

第二种方式:创建指定文件名称直接书写修改属性即可 推荐

2.上传配置文件到宿主机指定目录 (如: /root/redisconf/redis.conf)
3.数据卷挂载配置启动

docker run -p 6379:6379 -d --name redis02 --restart=always -v /root/redisconf:/data redis:5.0.12 redis-server 容器内配置文件路径

#例
docker run -p 6379:6379 -d --name redis02 --restart=always -v /root/redisconf:/data redis:5.0.12 redis-server /data/redis.conf

第一种方式因为配置文件没有开启远程访问权限,我们还要 cd 到 redisconf 目录下,vim 编辑器修改配置文件,找到 bind ,ip 改为 0.0.0.0 ,这样我们外界才可以连接上 docker 内的redis容器

第二种方式比如我们创建一个 redis.conf 文件,里面值修改 appendonly yes 和 appendonlyfilename 两个选项,还是像上面一样运行容器,外界一样可以访问到


3、docker运行nginx服务

1.docker hub 搜索 nginx

docker search nginx
2.下载对应镜像
docker pull nginx:1.19.10
3.运行 nginx
a.启动 nginx 映射端口(80)
docker run -p 80:80
b.启动 nginx 映射端口 后台启动 总是启动 指定名称
docker run -p 81:80 -d --restart=always --name nginx01 nginx:1.19.10
c.启动 nginx 映射端口 后台启动 总是启动 指定名称 加载指定的nginx配置启动-v 宿主机配置文件目录:/etc/nginx/nginx.conf

1. 实现反向代理 负责均衡

拷贝文件:docker cp 容器id:/etc/nginx/nginx.conf ~/DPFS/data/nginxconfig/

docker run -p 80:80 -d --restart=always --name nginx01 -v ~/DPFS/data/nginxconfig/nginx.conf:/etc/nginx.conf nginx:1.19.10

2. nginx服务器

docker run -p 80:80 -d --restart=always --name nginx01 -v 宿主机目录:/nginx/home目录 nginx:1.19.10

docker run -p 80:80 -d --restart=always --name nginx01 -v ~/DPFS/data/nginx/html:/usr/share/nginx/html nginx:1.19.10

4、docker运行ElasticSearch服务

1.docker hub 确定版本

docker search elasticsearch

2.下载镜像

docker pull elasticsearch:7.16.2

3.运行 ES

1.启动ES 映射端口(9200(http) 9300(tcp))
docker run -p 9200:9200 -p 9300:9300 elasticsearch:7.16.2
2. 启动es 映射端口 后台启动 总是启动 指定名称
docker run -p 9200:9200 -p 9300:9300 -d --restart=always --name es elasticsearch:7.16.2
3. 启动es 映射端口 后台启动 总是启动 指定名称 通过数据卷映射数据到宿主机。

容器内数据存储目录(/usr/share/elasticsearch/data)

docker run -p 9200:9200 -p 9300:9300 -d --restart=always --name es -v ~/DPFS/data/elasticsearch-data/data:/usr/share/elasticsearch/data elasticsearch:7.16.2
4. 启动es 映射端口 后台启动 总是启动 指定名称 通过数据卷映射数据到宿主机 通过数据卷将配置映射宿主机
docker run -p 9200:9200 -p 9300:9300 -d --restart=always --name es -v esdata:/usr/share/elasticsearch/data -v 		 /root/esconfig/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml elasticsearch:7.16.2

4.设置 ik 分词器启动

docker run -p 9200:9200 -p 9300:9300 -d --restart=always --name es -v esdata:/usr/share/elasticsearch/data -v 		 /root/esconfig/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /root/esplugins:/usr/share/elasticsearch/plugins elasticsearch:7.16.2
1.下载 ik 分词器

访问 github:搜索 elasticsearch-analysis-ik 选择medcl

选择 tags,找到对应的版本,我上面用的是 7.16.2的,点击下载 zip 包即可,在 linux 系统中可以使用 wget 下载链接地址 ,直接下载到 linux 系统中

注意:ik 分词器要求必须和 ES 版本一致

yum install -y wget

wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.16.2/elasticsearch-analysis-ik-7.16.2.zip

wget url -P 路径目录 ----------指定下载位置

2.创建 esplugins 目录
mkdir esplugins
3.解压缩 ik 到指定目录
yum install -y unzip
unzip elasticsearch-analysis-ik-7.16.2.zip

注意:

ES 启动如果没有指定单机方式运行,默认使用集群方式启动,如果使用集群方式启动在启动时会出现如下错误:

max virtual memory areas vm.max_map_count [65530] is too low ,increase to at least [262144]

宿主机内存太低了

解决方案:在宿主机中执行如下操作

1.在centos虚拟机中,修改配置sysctl.conf

vim /etc/sysctl.conf

2.加入如下配置

vm.max_map_count=262144 

3.启用配置

sysctl -p

注:这一步是为了防止启动容器时,报出如下错误:

bootstrap checks failed max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]

5.ERROR: [1] bootstrap checks failed

[1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
ERROR: Elasticsearch did not exit normally - check the logs at /usr/share/elasticsearch/logs/docker-cluster.log
解决方案:

在安装命令中添加 -e "discovery.type=single-node"

discovery.type=single-node表示单节点

docker run -d --name elasticsearch -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 -v /esdata:/usr/share/elasticsearch/data elasticsearch:7.16.2

6.设置 ik 分词器启动报异常:

Exception in thread "main" java.nio.file.NotDirectoryException: /usr/share/elasticsearch/plugins/.DS_Store
解决方案:

cd 到映射的宿主机的 es 的 plugins 目录中,ls-al 查看所有文件,rm -rf DS_Store 删除该文件即可


5、docker运行ES客户端工具kibana

1.docker hub

kibana :和 ES 版本保持一致

2.下载 kibana 镜像

docker pull kibana:7.16.2

3. 启动 kibana

a.启动 kibana 开放端口(5601)
docker run -p 5601:5601 -d --name kibana --restart=always kibana:7.16.2
b.启动 kibana 开放端口 指定 kibana连接ES服务
docker run -p 5601:5601 -d --name kibana -e ELASTICSEARCH_HOSTS=http:localhost:9200 --restart=always kibana:7.16.2

注意:默认连接就是 localhost:9200 ,es kibana 在一台机器上

注意:

1. 首先启动Elasticsearch

2. 查询Elasticsearch的内网ip

docker inspect --format '{{ .NetworkSettings.IPAddress }}' 容器id

3. 启动kibana,这里ELASTICSEARCH_HOSTS使用Elasticsearch容器的内网ip

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://172.17.0.2:9200 -p 5601:5601 -d kibana:7.16.2

没有按照上面的第3步骤,起不来kibana,会报错:Kibana server is not ready yet


八、dockerFile简介和使用

一、什么是 dockerFile

定义:

dockerFile 镜像描述文件 ===> dockerFile ===>新镜像

作用:

dockerFile 用来帮助我们构建自己的镜像

二、为什么是 dockerFile

docker 官方为我们提供很多官方镜像,为什么需要使用 dockerFile 镜像?

原因:docker 官方提供镜像非常官方,非常通用,这个镜像不能涵盖我们自己项目的相关操作

主要原因:我们日后希望基于自己公司不同项目定制不同镜像,方便部署维护

三、dockerFile 全部命令

保留字

作用

FROM

当前镜像是基于哪个镜像的 第一个指令必须是FROM

MAINTAINER

镜像维护者的姓名和邮箱地址

RUN

构建镜像时需要运行的指令

EXPOSE

当前容器对外暴露出的端口号

WORKDIR

指定在创建容器后,终端默认登录进来的工作目录,一个落脚点

ENV

用来在构建镜像过程中设置环境变量

ADD

将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar包

COPY

类似于ADD,拷贝文件和目录到镜像中 将从构建上下文目录中<原路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

VOLUME

容器数据卷,用于数据保存和持久化工作

CMD

指定一个容器启动时要运行的命令 Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

ENTRYPOINT

指定一个容器启动时要运行的命令 ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及其参数

四、使用dockerFile

1. 下载 centOS7 镜像,我们基于这个镜像学习

2. 在宿主机创建一个目录,里面 touch 一个Dockerfile 文件

3. vim Dockerfile 第一个 FROM 命令,基于哪个镜像。第二个 RUN 命令

FROM centos:7
#RUN yum install -y vim 			给构建的镜像的系统安装 vim 编辑器
#RUN yum install -y wget 		    给构建的镜像的系统安装wget
RUN ["yum","install","-y","wget","vim"]		也可以像这样用数组的方式写

4. build构建

docker build -t centos7:01 

-t 表示指定镜像名字,.表示当前目录下,需要包含 Dockerfile 文件

5.查看镜像

 docker images 

6.运行镜像并进入镜像交互

docker run -it centos7:01

九、DockerFile

FROM centos:7			#基于哪个镜像构建
#RUN yum install -y vim	#给构建的镜像的系统安装 vim 编辑器
#RUN yum install -y wget 		#给构建的镜像的系统安装wget
RUN ["yum","install","-y","wget","vim"]		#也可以像这样用数组的方式写

EXPOSE 8080/tcp											#EXPOSE表示当前容器对外暴露的端口号,只有暴露了容器的端口号,日后宿主机才能映射到你容器暴露的这个端口号
#EXPOSE 9200/udp
EXPOSE 9300 	如果没有显式指定默认暴露都是 tcp 协议		

WORKDIR /data 	#指定容器启动时进入的默认路径
WORKDIR aa		#WORKDIR 指定进入容器内的目录位置,可以写绝对路径,也可以写相对路径,可以写多个,如果后面的写了绝对路径,表示覆盖。如果像 aa 这样相对路径,会进入/data/aa ,没有 aa 目录会自动创建
WORKDIR	bb		#docker run -it 镜像名|id  	这样进入容器就是 /data/aa/bb 下了

ENV	BASE_DIR /data/bb		#ENV用来构建镜像设置环境变量,采用 key value 形式或者key=value 	BASE_DIR /data/bb 就是把 /data/bb 定义为 BASE_DIR 这样一个变量,后面我们就可以引用 BASE_DIR 代表/data/bb ,使用$BASE_DIR 引用 。如果公共的地方使用较多,我们就可以使用 ENV 设置环境变量使用。如
#COPY aa.txt $BASE_DIR
#ADD aa.txt $BASE_DIR

COPY aa.txt /data/bb		# 用来将context目录中指定文件复制到镜像的指定目录中

ADD bb.txt /data/bb			# 用来从context上下文复制新文件、目录或远程文件url,并将它们添加到位于指定路径的映像文件系统中。
ADD https://dlcdn.apache.org/tomcat/tomcat-10/v10.0.14/bin/apache-tomcat-10.0.14.tar.gz /data/bb		#可以下载压缩包到指定位置
ADD apache-tomcat-10.0.14.tar.gz /data/bb #也可以将压缩包下载到 context 目录(就是包含 Dockerfile 文件的目录里面),我们在构建镜像的时候会直接解压到镜像的指定目录里面。通过 url 的方式的话只会下载到指定目录,不会解压
RUN mv apache-tomcat-10.0.14 tomcat  #可以让 RUN 命令执行将解压后的目录改名为 tomcat
WORKDIR tomcat 			#因为上面进入的目录是/data/bb ,现在我们再指定相对目录tomcat,所有我们现在进入的就是 bb 下的 tomcat 目录了

VOLUME	/data/bb/tomcat/webapps 	#表示该路径的目录可以被挂载到宿主机
					
ENTRYPOINT ls $BASE_DIR/tomcat 		#ENTRYPOINT用来指定容器启动时执行命令,和CMD类似。因为 ls 不会阻塞容器执行,所以 ls 展示完目录之后,容器会结束掉。因为centos操作系统没有服务运行。如果使用 -it 的模式运行,进入容器内部,会阻塞容器,此时容器不会结束掉,我 exit 退出才会结束掉。[RUN 是在构建中执行,ENTRYPOINT 和 CMD 是容器启动时执行的]
ENTRYPOINT tail -f aa.txt #查看日志这种方式也会阻塞容器结束,此时我们 ctrl+C 退出查看,容器也会正常结束 

CMD ls /data/bb/tomcat 		#CMD 和 ENTRYPOINT 功能类似,CMD 可以有多个,但是只能以最后一个为准,前面的会被最后一个给覆盖掉,所以写多个没有用。ENTRYPOINT 可以有多个。
#我们可以在运行容器的时候,在后面加指令覆盖 CMD 的指令。比如 docker run centos:7 echo "i love you" ,这样容器运行的时候就不会执行 CMD 的 ls 命令,会执行 echo 的打印命令
# CMD 的命令我们在 docker run 运行容器后面可以使用命令去覆盖,但是 ENTRYPOINT 的命令我们要想覆盖,需要在 docker run后面加一个参数 --entrypoint=命令 然后后面再写执行的数据,如
ENTRYPOINT ls /data/bb/tomcat
#我们启动容器执行 docker run --entrypoint=ls centos7:1 /data/bb/tomcat
#所有 ENTRYPOINT 指令一般写固定写死的东西,CMD 来给它传参数。如
#ENTRYPOINT ls /data
#CMD /data/bb				#这样的意思是 ENTRYPOINT 中有一个默认的 ls /data 默认指令,然后 CMD 中不写命令只写参数,这样参数就会传给 ENTRYPOINT 的命令。覆盖掉上面的参数,原来要查的是/data ,覆盖掉之后查的是/data/bb 。注意:要覆盖的话要使用 json 的格式
ENTRYPOINT ["ls","/data"]
CMD ["/data/bb"] 	#build 构建好之后,docker run centos7:2 ,后面什么也不会,会执行 ls /data ,然后执行/ls /data/bb。 如果 docker run centos7:2 /data/bb/tomcat  这样传参的形式运行,会执行 ls /data 查看,然后执行 ls /data/bb/tomcat,就是我们的参数把 CMD 的参数给覆盖掉了。
#我们也可以在 ENTRYPOINT 中只写一个命令写死,不写参数,后面 CMD 来写参数,我们可以 run 启动的时候传参
ENTRYPOINT ["java","-jar"]
CMD ["ems.jar"] 		#我们日后可以构建镜像的时候使用命令把 jar 包拷贝到目录里面,默认使用 ems.jar 启动 jar 包,如果不叫 ems.jar,我们可以 docker run 的传参覆盖 ems.jar

十、DockerFile构建SpringBoot应用

1.开发 SpringBoot 应用程序

2.对 SpringBoot 应用程序进行打包

war 过渡 ===> tomcat

jar 主流 ===> jdk

3.打包项目

打包成 如:demo.jar

4.在服务器中创建 dockerfile 上下文目录 context

1. 创建目录

mkdir demo 	

这个目录作为 context 目录

2.在 demo 目录中创建 Dockerfile 文件

touch Dockerfile

3.上传应用 jar 包到 context 目录

4.编写 Dockerfile

FROM openjdk:8-jre		#基于哪个镜像进行构建
WORKDIR /app					#定义进入容器时默认位置,接下来后续操作工作位置
ADD demo.jar app.jar	#将上下文中名字为 demo.jar 复制到工作目录,同时修改名称为 app.jar
EXPOSE 8081						#让当前容器暴露哪个端口,因为项目使用端口是 8081
NTRYPOINT ["java","-jar"]	#启动应用的固定命令
CMD ["app.jar"]				#执行 jar名称

5.执行构建

docker build -t demo:01

在 Dockerfile文件所在的目录下才能执行

6.运行容器

docker run -d -p 8081:8081 --name demo demo:01

7.访问

localhost:8081/hello


十一、Idea中编写DockerFile插件

1.安装 Docker 插件

2.在项目中直接创建 Dockefile 文件即可

3.在 idea 中可以远程连接 SFTP

  1. 点击顶栏Tools

  2. 点击 Deployment(部署)

  3. 选择 Browse Remote Host(浏览远程主机)

  4. 点击上面的 ... ,添加远程主机

  5. Name 自定义,一般建议使用 ip 地址标识哪台服务器。Type 选择 SFTP(安全文件传输协议)

  6. 填写 SFTP host:远程主机 ip (没有看到的话点击 SSH configuration 旁边的 ...)

  7. 端口默认 22

  8. User name and Password:输入远程主机的用户名和密码

  9. 连接成功后就可以读到远程主机的文件了

  10. 连接的时候还可以在 Root path 指定只读某一个目录

  11. 我们可以新建一个 context 上下文目录,创建 Dockerfile 文件,这样我们在 idea 中编写的 Dockefile,点击上面的上传箭头同步一下,就是服务器的 Dockerfile 文件了。编写好的 jar 可以直接拖到远程主机 context 目录中


十二、容器间通信之网络使用

容器间通信

说明

容器之间通过网络进行相互通信

官方说明

当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。

同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 (opens new window)中定义)中的一个地址给 docker0 接口。比如典型的 172.17.42.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。

当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。

例子

1.启动tomcat01 、02 、03 三个容器
docker run -d -p 8080:8080 --name tomcat01 tomcat:latest
docker run -d -p 8081:8080 --name tomcat02 tomcat:latest
docker run -d -p 8082:8080 --name tomcat03 tomcat:latest
2.查看容器 ip ,在Networks位置
docker inspect tomcat01|02|03

#"IPAddress": "172.17.0.2"
#"IPAddress": "172.17.0.3"
#"IPAddress": "172.17.0.4"
3.随便进入一个容器,访问其它两个容器
docker exec -it tomcat01 bash

上面查看 03 的 ip 是 172.17.0.4

我们进入到 01 容器内,curl http://172.17.0.4:8080 ,curl 表示发请求,如果返回的是主页index.html源码,表示已经建立通信了(我mac访问不到,进入容器内 rm -rf webapps ,mv webapps.dist webapps 就可以访问到了)

总结

  1. 默认 docker 在创建容器时将所有容器都连接到 docker0 网桥上,默认在 docker0 网桥的容器都可以使用容器内 ip 地址进行通信

2.默认 docker 在创建容器时将所有容器都连接到 docker0 网桥上,默认在 docker0 网桥的容器都可以使用容器名称作为容器 ip 进行通信

注意:使用容器名称必须自定义网桥不能使用默认 docker0

例:进入容器内部,使用 curl http://tomcat02:8080 ,一样可以获取到 index.html 源码,说明已经建立通信。使用名字进行通信就不用担心容器宕机或重启,ip 地址发生变化连接不上的问题了。如果 ip 变更了。容器名字会马上绑定这个 ip 的。

建议一个项目一个网桥

自定义网桥实现网桥中一组容器中的通信

1.docker 中网桥类型
docker network list

#NETWORK ID     NAME      DRIVER    SCOPE
#5c89c33dfccb   bridge    bridge    local
#c6564d7e2762   host      host      local
#8e88560ecb17   none      null      local

docker 中网络类型:

bridge:桥

host:仅主机,仅容器自身

none:不使用任何网络

2.创建网络自定义桥

使用 network 的相关命令,可以 docker network --help 查看命令帮助

docker network create -d bridge 网络名称			

-d 表示指定网络类型,bridge 是默认的

3.查看网络
docker network ls
4.查看某一个网络细节
docker network inspect 网络名
5.删除一个网络
docker network rm 网络名

docker network prune 		#删除所有未被用到的网络名
6.运行多个容器在指定网络中
a.启动容器时明确指定容器使用哪个网络
docker run -d --network 网络名称 ...
b.启动之后容器加入某个网络中

实例,创建两个容器,希望在启动的时候指定在同一个网络里面

1.


docker network create -d bridge sx

2.

docker run -d -p 8080:8080 --name tomcat01 --network sx tomcat:latest
docker run -d -p 8080:8080 --name tomcat02 --network sx tomcat:latest

3.

docker network inspect sx

查看网络细节内的 Container,看看两个容器是否都在这个网络里面

都在的话可以进入容器内部 ,访问另一个容器

curl http://容器ip:8080

curl http://容器名字:8080

启动容器之后容器加入到某个网络中

docker network connect 网络名 容器id(name)
docker network connect sx tomcat01
docker network connect sx tomcat02
docker network connect sx tomcat03
docker network inspect sx   # 查看网络细节

此时我们进入到tomcat01容器内部

curl tomcat02
curl tomcat03

都能获取到 index.html 页面源码


十三、高级数据卷(数据卷原理)

1、数据卷 Volume

定义

用来实现宿主机和容器之间文件目录映射同步

2.数据卷使用

-v 宿主机路径:容器内路径

注意:必须在容器首次启动时指定

a.使用绝对路径数据卷

docker run /root/datas:/usr/local/tomcat/webapps ... tomcat:8.0

b.使用别名方式数据卷

docker run -v bb:/usr/local/tomcat/webapps ... tomcat:8.0

注意:

bb代表一个数据卷别名

bb 这个数据卷别名可以存在,也可以不存在,不存在 docker 首次用到时会自动创建

第一次使用别名时将容器中原始数据保留下来,使用绝对路径方式不会保留容器中原始数据

3.别名到底是什么

别名代表一个 docker 自身维护数据卷

1.查看所有 docker 维护数据卷

docker volume ls

2.查看数据卷详细内容

docker volume inspect 数据卷别名

docker inspect 数据卷别名、网桥名称、容器名称

3.删除一个数据卷

docker volume rm 数据卷别名

4.创建一个别名数据卷

docker volume create 数据卷别名

十四、docker-compose

一、引入

现有 docker 进行项目部署存在问题

1.为了完成一个完整项目势必用到 N 多个容器配合完成项目中业务开发,一旦引入 N 多个容器之间就会形成某种依赖,也就意味着某个容器某些容器运行需要其它容器先启动之后才能正常运行。

容器编排显得至关重要

2.现在这种方式使用容器,没有办法站在项目的角度将一个项目用到一组容器划分到一起,日后难点在于项目多服务器部署

项目角度管理项目用到一组容器

二、docker-compose编排项目

1.什么是 docker-compose

定义:

'Compose'项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的 "快速编排"

"快速编排":站在项目角度将一组相关联容器整合在一起,对这组容器进行按照指定顺序启动

compose 定位对于多个 docker 容器管理

2.如何使用 docker-compose项目

docker-compose.yml 就是应用(project) 应用(project)就是 docker-compose.yml

Project:项目,由一组关联的应用容器(服务)组成的一个完整业务单元,在'docker-compose.yml'文件中定义

Service:服务,一个项目中某一个容器,称之为一个服务

3.docker-compose 安装

注意:只有 linux 平台上在安装docker 时没有安装 docker-compose ,windows、macOS 安装 docker 时自动安装 docker-compose,不用再单独安装

1.在线安装
sudo curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 

赋权

sudo chmod +x /usr/local/bin/docker-compose
2.离线安装

1.下载 docker-compose 脚本

2.放入/usr/local/bin 此目录已经配置了环境变量的

3.sudo chmod +x /usr/local/bin/docker-compose

4.docker-compose 一案例

a.创建一个项目
mkdir ems
b.在 ems 目录创建一个 docker-compose.yml 模板文件
touch docker-compose.yml
vim docker-compose.yml

version:docker-compose 版本和 docker 版本对应关系 https://docs.docker.com/compose/compose-file/compose-file-v3/

c.书写 docker-compose,如下面的 yml 文件
d.启动 docker-compose 一组服务
docker-compose up -d 

指定这个命令必须在 docker-compose.yml配置文件的目录中 , -d 表示后台启动服务

docker-compose down  #关闭容器并把之前缓存清除

三、docker-compose.yml

# 代表使用 docker-compose 项目的版本号,这个版本号和 docker 引擎有关系,可以到 docker 官网Docs的Reference的Compose查看 docker-compose 对于 docker 引擎要求的最低版本,docker version 查看 docker 引擎版本
version: "3.8"

services:
 tomcat:								#服务名,自定义,但是要唯一
 	container_name: tomcat01		#代表给当前容器指定一个名称,类似于 docker -run 后面的 --name 容器名,建议使用默认名称,由 docker-compose 自动创建即可,这里我们可以不用指定这个参数
  image: tomcat:8.0		#代表使用的哪个镜像,类似于 docker run 最后指定的镜像名称
	 ports:						 #代表宿主机和容器中端口映射,类似于 docker run -p 参数,可以写多个
    - 8080:8080
		- 8081:8080
			
 tomcat:
  image: tomcat:8.0
   ports:
    - 8082:8080
			
 redis:
  images: redis:5.0.12
  ports:
   - "6379:6379"  	#ports 也可以写成 String 类型的
 
 mysql:
  image: mysql:5.6
  ports:
   - "3306:3306"
  environment: 		#代表给当前容器启动指定环境。我们在 docker run 启动 mysql 的时候,需要使用-e MYSQL_ROOT_PASSWORD=密码 ,指定环境,所以在 yml 文件中需要指定 environment 参数
   - "MYSQL_ROOT_PASSWORD=root" 		#也可以写成 - MYSQL_ROOT_PASSWORD: root   root 表示密码
  volumes:				#代表给当前容器和宿主机指定数据卷 类似于 docker run -v 宿主机目录:容器内目录 	注意:docker-compose 使用绝对路径要求必须先创建才能使用
   #- /root/mysqldata1:/var/lib/mysql		#在 docker-compose 中,要求宿主机绝对路径一定要存在,不会自动创建
   - mysqlData:/var/lib/mysql						#在 docker-compose 中使用数据卷别名的时候,需要先声明数据卷别名,启动的时候才会创建这些数据卷。自动创建的数据卷名字前面会加上项目名,如ems_mysqlData
   
volumes:
 mysqlData:		#声明数据卷别名

四、idea中编写docker-compose

1.在 idea 中远程连接 linux 主机

2.在 root 目录下新建一个 dangdang 目录

3.在 dangdang 目录下新建 docker-compose.yml

4.编写 docker-compose.yml 文件,然后点击上传

5.cd 到/root/dangdang 目录里面,docker-compose up 启动

五、docker-compose中的模板命令

# 1.docker-compose
a. build 指令		通过 docker-compose 在启动容器之前先根据 Dockerfile 构建镜像,然后根据构建的镜像启动容器
b. command 指令		覆盖容器启动之后默认执行的命令
c. container_name 指令	用来指定 docker-compose 启动容器名称		注意:不推荐指定容器名称
d. depends_on	指令	解决容器的依赖、启动先后的问题
			注意:当前服务不会等待被依赖服务[完全启动]之后才启动
e. environment 指令		用来给容器启动指定环境变量  相当于 docker run -e 选项
f. env_file	指令		
g. expose 指令	用来指定构建镜像过程中容器暴露的端口号,我们一般在 Dockerfile 中指定,在 docker-compose.yml 中一般不用
h. images 指令	用来指定启动容器使用镜像是谁 相当于 docker run image(镜像名)
i. networks 指令		用来指定启动容器使用的网桥  相当于 docker run --network  ,在 docker-compose.yml 中使用需要先声明网桥
j. ports 指令		用来指定宿主机和容器端口映射	相当于 docker run -p 
k. volumes 指令		用来指定宿主机中目录和容器中目录映射 ,使用别名的方式需要先声明别名数据卷 相当于 docker run -v
l. restart 指令 用来指定 docker 容器(服务)总是运行 相当于 docker run --restart=always 

docker-compose.yml

version: "3.8"

#管理一组服务
services:
 
 tomcat:
  image: tomcat:8.0
  ports:
   - "8080:8080"
  networks: 	#需要先声明网桥
   - dangdang
 
 apps:
  #build: ./ #指定 DockeDfile的上下文目录 一切都是默认值
  
  build:		 #也可以指定相关参数
   context: ./ 			#用来指定Dockerfile上下文目录
   dockerfile:			#指定 Dockerfile 文件名称
  ports:
   - "8081:8081"
  command: ["test.jar"]		#用来覆盖容器启动之后默认指令,类似于 docker run image 覆盖的命令 (比如覆盖Dockerfile 中 CMD的命令)
  depends_on:
  	- tomcat		#书写依赖的服务名
  	#- mysql
  	#- redis
  	#- es
  networks:
   - dangdang
  	
  mysql:
   image: mysql:5.6
   ports:
   	- "3306:3306"
   #environment::shixiang   
    #- MYSMYSQL_ROOT_PASSWORD:shixiang
   	#- "MYSQL_ROOT_PASSWORD=shixiang"
   env_file:
    - ./.env				#当前目录中编写 .env 文件,里面像上面 "MYSQL_ROOT_PASSWORD=shixiang" 一样编写环境即可了 ,在 liunx 中 .开头的文件默认是隐藏文件,更安全
   networks:
    - dangdang
   volumes:
    - mysqlData:/var/lib/mysql
    
  es:					#docker run -d -p 9200:9200 -p 9300:9300 --restart=always -v ... 		可以参考着写
   image: elasticsearch:6.8.10
   ports:
    - "9200:9200"
    - "9300:9300"
   restart: always
   volumes:
    - esData:/usr/share/elasticsearch/data
    
   rabbitmq:
    image: rabbitmq:management
    ports: 
     - "15672:15672"
     - "5672:5672"
    #environment:
     #- "RABBITMQ_DEFAUL_USER=admin"
     #- "RABBITMQ_DEFAUL_PASS=admin"
    env_file:
     - ./.env
# 声明使用网桥
networks:
 dangdang:
 
#声明别名数据卷
volumes:
 mysqlData:
 esData:

六、docker-compose命令说明

docker-compose 命令

可以针对项目|项目中某个服务

注意:没有特殊说明时,默认都是对项目操作

语法

docker-compose -f docker-compose.yml 命令 [选项] [服务id]

a. up [服务id]

docker-compose up 		#对整个项目操作
docker-compose 服务id	#对当前 docker-compose 中对应服务 id 容器操作

作用:该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作

b. down

docker-compose down 			#对整个项目操作
docker-compose down 服务id 

作用:docker-compose down 关闭所有容器 并移除网络

c. exec

docker-compose exec 服务id bash

作用:进入某个容器内部

d. ps

docker-compose ps

作用:列出所有运行的服务

e. restart -t 20s

-t 表示--timeout TIMEOUT,停止容器的超时时间,默认 10s

docker-compose restart 	#对整个项目操作
docker-compose restart -t 服务id 		

作用:重启整个项目或者指定 id 服务

f. rm

docker-compose rm [服务id]

可以加 -f 强制删除,运行中的容器也会删除

-v 表示连数据卷也删除

作用:删除整个项目或者指定 id 服务

g. top

docker-compose top [服务id]

作用:查看整个项目中所有服务容器内运行进程或者查看某个指定 id 服务的容器的进程

h. pause 暂停 和 unpause 恢复

 docker-compose pause|unpause [服务id]

作用:暂停和恢复整个项目所有服务或者指定 id 某个服务

i. logs

docker-compose logs -f(实时) [服务id]

作用:查看整个项目中所有服务运行日志 或者指定服务 id 服务的运行日志


十五、portainer docker可视化界面

一、简介

第三方公司开源 Portainer项目 ,用来对 docker 引擎中运行所有容器进行可视化的展示

二、如何使用

docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

三、访问虚拟机ip:9000端口

默认用户 admin,首次是没有密码的,可以直接输入指定一个密码


消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息

备案号:粤ICP备2024164527号-1