Docker学习|Java后端必备技能|入门一篇就够了

Docker学习

平常的产品发布的时候,我们根据不同平台需要配置不同的环境,大大增加了我们的工作。而Docker就可以简化我们的工作,Docker镜像的设计,使得Docker得以打破过去**「程序即应用」**的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。

可以想象成Docker就是简单的虚拟机。

Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。

  • 那么docker和虚拟机有什么区别呢?

  • Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口

  • 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。

    Docker与虚拟机架构对比图:

Docker学习|Java后端必备技能|入门一篇就够了_第1张图片

Docker学习|Java后端必备技能|入门一篇就够了_第2张图片

Docker的安装

Docker 支持以下的 64 位 CentOS 版本:

  • CentOS 7
  • CentOS 8
  • 更高版本…
  1. 卸载干净之前的docker
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 安装依赖包
sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
  1. 设置阿里云镜像源
sudo yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装 Docker-CE
sudo yum install docker-ce
# 如果不能成功就先更新yum软件包索引
# sudo yum makecache fast
  1. 启动 Docker。
# 开机自启
sudo systemctl enable docker 
# 启动docker服务  
sudo systemctl start docker
  1. 通过 docker version 验证是否正确安装了 Docker Engine-Community 。
docker version

接下来是一些可选配置,建议设置!

  • 添加docker用户组(可选)
# 1. 建立 Docker 用户组
sudo groupadd docker
# 2.添加当前用户到 docker 组
sudo usermod -aG docker $USER
  • 镜像加速配置
# 加速器地址 :
# 阿里云控制台搜索容器镜像服务
# 进入容器镜像服务, 左侧最下方容器镜像服务中复制加速器地址
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["你的加速器地址"]
}
EOF
# 重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker

Docker 镜像

1.镜像是什么?

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

(1)UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,Union文件系统是Dokcer镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的镜像。

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

(2)Docker镜像加载原理

docker的镜像实际上是由一层一层的文件系统构成,这种层级的文件系统UnionFS。

主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的linux/unix系统是一样的,包含boot加载器内核。当boot加载完之后整个内核就都在内存中了,此时内存的使用权已经由bootfs交给内核了,此时系统也会卸载bootfs

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M

在这里插入图片描述

对以一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就行,因为底层直接用host和kernel,自己只需要提供rootfs就行。由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。

(3)分层的镜像

以pull为例,在下载的过程中我么可以看到docker的镜像好像是在一层一层的下载

(4)为什么Docker镜像要采用这种分层的结构

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

比如:有多个镜像都从相同的base镜像构建而来,那么宿主机只需要在磁盘上保存一份base镜像,同时内存中也需要加载一份base镜像,就可以为所有服务器服务了。而且镜像的每一层都可以被共享。

2.特点

docker镜像都是只读的

当容器启动时,一个新的可写层被加载到镜像的顶部。

这一层通常被称作“容器层”,“容器层”之下都叫“镜像层”

镜像分层的好处

最大的一个好处就是 :共享资源,节约空间

比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,

同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

常用命令

1. docker version

# 可以查看当前的 docker 版本信息
[zztroot@localhost ~]$ docker version
Client: Docker Engine - Community
 Version:           19.03.12
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:46:54 2020
 OS/Arch:           linux/amd64
 Experimental:      false
# 后面省略不显示

2. docker info

# 查看docker系统信息
[zztroot@localhost ~]$ docker info
Client:
 Debug Mode: false
Server:
 Containers: 1
  Running: 0
# 后面省略不显示

3. docker --help

# 查询docker的指令
[zztroot@localhost ~]$ docker --help
# 下面会显示多个指令的意思,也会有子指令的提示

# 还可以通过下面方式查看某个指令的用途
zztroot@localhost ~]$ docker pull --help

Usage:	docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Pull an image or a repository from a registry

Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)
      --platform string         Set platform if server is multi-platform capable
  -q, --quiet                   Suppress verbose output

4. docker images

# 查询目前的镜像
[zztroot@localhost ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0d120b6ccaa8        7 days ago          215MB
mysql               latest              0d64f46acfd1        13 days ago         544MB
hello-world         latest              bf756fb1ae65        7 months ago        13.3kB

5. docker search

# 搜索指定镜像,举例搜索mysql
[zztroot@localhost ~]$ docker search mysql
NAME	 DESCRIPTION									 STARS	OFFICIAL AUTOMATED
mysql    MySQL is a widely used, open-source relation…   9854	 [OK]                
mariadb  MariaDB is a community-developed fork of MyS…   3599             [OK]       
percona  Percona Server is a fork of the MySQL relati…   502              [OK]         

6. docker pull

# 拉取镜像,冒号输入的是版本号,也可以不输入,默认拉取lastest标签的镜像
docker pull name:tag

[zztroot@localhost ~]$ docker pull java
Using default tag: latest
latest: Pulling from library/java
5040bd298390: Pull complete 
fce5728aad85: Pull complete 
76610ec20bf5: Pull complete 
60170fec2151: Pull complete 
e98f73de8f0d: Pull complete 
11f7af24ed9c: Pull complete 
49e2d6393f32: Pull complete 
bb9cdec9c7f3: Pull complete 
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:latest
docker.io/library/java:latest

7. docker rmi

# 移除某个镜像
docker rmi bf756fb1ae65 #通过docker images查看要移除镜像的id
# 如果报错,可能是该镜像还有容器再使用,建议看一下是否要删除
docker rmi -f  bf756fb1ae65 # 强制删除指令

8. docker ps

# 显示目前正在运行的容器
[zztroot@localhost ~]$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
41515b7bc337        centos              "/bin/bash"         About a minute ago   Exited (0) About a minute ago                       mycentos
# 如果不输入-a就不能看见历史记录,只能看见当前运行的

9. docker run

# 实例化某个镜像,-p代表 主机端口:容器端口 --name 设置名字
docker run -p 8080:8080 --name mycentos centos

# 实例化完我们会发现,采用ps指令没有出现该容器,原因是机制认为该容器未被使用,所以自己暂停了
docker run -d centos #后台运行,守护进程的方式
docker run -it centos #进入交互界面
#以上两种可以进入容器

10. exit

# exit可以关闭并退出容器
exit
# CTRL + P + Q ,可以不关闭,退出容器(无所谓大小写)

11. attach、exec

# attach、exec都需要保证容器在运行才可以
docker attach 容器id
docker exec -it 容器id [指令]
# 区别在于前者进入执行,后再可以在外层发出指令,让容器执行,并保持在外层

12. docker rm

# 删除容器 docker rm 容器id
zztroot@localhost ~]$ docker rm $(docker ps -aq)
41515b7bc337
bda10e7bec92
# $(docker ps -aq) 的意思是删除所有容器,你也可以指定容器

13. docker inspect

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

14. docker logs

# 查看容器的日志,-f代表实时更新,--tail后面要加数字(选择后面第n条开始)
docker logs -f -t --tail 3 [容器id]

15. start、stop、kiil

# 启动容器
docker start 容器id
# 关闭容器
docker stop 容器id
# 强制关闭
docker kill 容器id

16. docker cp

# 复制容器内的文件到主机
docker cp  容器ID:容器内路径 目的主机路径

17. docker commit

docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
# 假设你的容器修改完了,你想保存这个镜像
[zztroot@localhost ~]$ docker commit -a="Gnight" -m="My Centos create zzt.txt" 92867844cfef mycentos_gnight:1.0
# 会返回id,可以通过docker images查询
sha256:82e54145035a497352cb97d79ac087e2e4c00991421ade9f77e76720f93c09a7

常用指令图

Docker学习|Java后端必备技能|入门一篇就够了_第3张图片

Docker数据卷

在Docker中,要想实现数据的持久化(Docker的数据持久化 == 数据不随着Container的结束而结束),需要将数据从宿主机挂载到容器中。

如果你学习过Redis,虽然它是内存数据库,但是也有RDB、AOF的持久化方式,可以再重启后自动恢复数据,不会因为关闭而导致数据丢失。

数据卷的使用

# 采用 -v 的方式创建数据卷
docker run -it -v /宿主机绝对路径目录:/容器内目录   镜像名 

# 方法2,先创建好数据卷,不采用目录的方式
docker volume create mycentos-vol # 创建一个自定义容器卷
docker volume ls # 查看所有容器卷
docker volume inspect mycentos-vol # 查看指定容器卷详情信息

# 如果不再使用自定义数据卷了,那么可以手动清理掉:
docker stop 容器id  # 暂停容器实例
docker rm 容器id # 移除容器实例
docker volume rm mycentos-vol # 删除自定义数据卷

# 补充说明,如果Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied
# 解决办法:在挂载目录后多加一个 --privileged=true 参数即可

操作示例:

假设我们要设置一个目录叫contact_vol,作为容器数据持久化的目录。

# 首先在 HOST 主机 操作实例化一个容器,并设置了数据卷目录
[zztroot@localhost myworkspace]$ docker run -it -v /home/zztroot/myworkspace/contact_vol:/docker_workspace/contact_vol centos

查看二者是否出现了一样的目录:

Docker学习|Java后端必备技能|入门一篇就够了_第4张图片
Docker学习|Java后端必备技能|入门一篇就够了_第5张图片

可以看到二者都出现了一样的 contact_vol 目录

# 主机和容器都可以修改该文件内容,并且都能查看到!

# 主机修改
[zztroot@localhost contact_vol]$ touch contact_vol
[zztroot@localhost contact_vol]$ ls
contact_vol
# 容器也看见
[root@b4d4a1c741b8 contact_vol]# ls
contact_vol

# 容器修改
[root@b4d4a1c741b8 contact_vol]# touch docker_add.txt
# 主机看见
[zztroot@localhost contact_vol]$ ls
contact_vol  docker_add.txt

补充:

当我们多个容器都和宿主机某个目录有数据卷的时候,那么他们相互之间都是互通的,数据卷的寿命周期一直到没有容器使用它为止。

DockerFile

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 平常我们通过pull拉取镜像,那么如果我们需要对镜像定制的时候咋办呢?我们可以通过编写DockerFile来实现镜像定制,这就是一个文件告诉我们该如何配置这个镜像,最后通过 build 指令创建镜像,可以通过 run 启动我们的镜像。

DockerFile语法知识:

  1. 每个保留字指令都是大写的,后面至少会跟着一个参数
  2. 从上至下按顺序执行
  3. 每条指令相当于一个镜像层
  4. 使用 # 注释

DockerFile指令

  1. FROM:基础镜像,当前是基于哪个镜像的
  2. MAINTAINER:作者<名称邮箱>
  3. RUN:容器构建时需要运行的命令
  4. EXPOSE:当前容器对外暴露的端口号
  5. ENV:构建时设置环境变量
  6. WORKDIR:进入容器的默认路径
  7. ADD: 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理url和解压tar压缩包
  8. COPY : 类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
  9. VOLUME:容器数据卷,用于数据保存和持久化工作
  10. CMD:指定一个容器启动运行时要运行的命令(只有最后一个生效)CMD会被docker run 后的命令覆盖
  11. ENTRYPOINT:指定一个容器启动运行时命令,命令不会覆盖或者被覆盖
  12. ONBUILD:当构建一个被继承的dockerFile时运行命令,父镜像在被子继承后父镜像的onbuild被触发(相当于一个回调)

单纯的说肯定没什么感觉,那就让我们讲一个示例,把每个保留字都用一下!

假设我们需要创建一个centos容器,由于这是精简的centos所以是没有vim,我们就给他装上vim。

# 首先创建DockerFile文件
vim DockerFile

# 编辑内容
# 从centos出发
FROM centos
# 设置作者和邮箱
MAINTAINER Gnight<[email protected]>
# 构建的时候要安装 vim
RUN yum -y install vim
# 对外暴露端口(指的是容器暴露的)
EXPOSE 80
# 配置环境变量
ENV START_PATH /usr
# 一开始进入终端后的位置,这里用环境变量替代了,也可以直接写目录
WORKDIR $START_PATH
# 设置容器卷
VOLUME /MyCentosWorkSpace
# CMD,只有最后一条生效,如果我们run的时候设置了别的指令,那么这条也不会执行
CMD /bin/bash
# 如果有容器继承(FROm)他,那么就打出来这句话
ONBUILD echo "hello , son !"

镜像创建指令:

docker build -f DockerFile -t mycentos:1.0 .
# 注意结尾有一个 . 一定不能缺失!!!!这是代表工作目录为当前!
# 当我们看见
Successfully built 21707a7bd77d
Successfully tagged mycentos:1.0
# 就代表创建成功了

# 查看我们创建好的镜像
[zztroot@localhost myworkspace]$ docker images
REPOSITORY	TAG		IMAGE ID		CREATED				 SIZE
mycentos	1.0		21707a7bd77d	About a minute ago   272MB
cento		satest  0d120b6ccaa8	8 days ago           215MB

那么实例化一下我们的镜像吧!

docker run -it --name father_centos -p 80:80 mycentos:1.0
  • ENTRYPOINT和CMD指令的区别在哪?

  • ENTRYPOINT属于不会被覆盖的,我们可以在run指令后继续添加完善这个指令,而cmd会被覆盖,如果DockerFile有多个CMD则只有最后一个生效,如果run指令后面添加了其他指令,那么原本的CMD也会失效。

# 创建DockerFile2
FROM centos
# 免得缺少curl
RUN yum -y install curl
# 设置entrypoint指令
ENTRYPOINT ["curl","-s","http://ip.cn"]
#------------------------------------------------------

#------------------------------------------------------
# 制造镜像
docker build -f DockerFile2 -t ipcheck:1.0 .
#------------------------------------------------------

# 可以直接在后面续上指令 -i 输出头信息
[zztroot@localhost myworkspace]$ docker run -it ipcheck:1.0 -i
# 以下是输出的信息
HTTP/1.1 403 Forbidden
Date: Wed, 19 Aug 2020 09:09:22 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 16
Connection: keep-alive
#后面省略……
  • ADD指令和COPY指令区别?

  • 我们找到了Docker hub中centos7的Dockerfile:(创建centos7的DockerFile详情)

    # scratch是基础镜像,大部分镜像都是这个发展起来的
    FROM scratch
    # 要保证含有该压缩包
    ADD centos-7-docker.tar.xz /
    
    LABEL org.label-schema.schema-version="1.0" \
        org.label-schema.name="CentOS Base Image" \
        org.label-schema.vendor="CentOS" \
        org.label-schema.license="GPLv2" \
        org.label-schema.build-date="20181006"
    
    CMD ["/bin/bash"]
    
  • ADD会拉取并自动处理(解压),而COPY仅仅是复制

SpringBoot打包镜像

我们如果想要把SpringBoot打包成镜像怎么办?

  1. 使用IDEA打包成JAR包,在target中可以找到

Docker学习|Java后端必备技能|入门一篇就够了_第6张图片

  1. 编写DockerFile
FROM java:8

# 要让这条指令实现,前提是:将我们的jar包复制出来,放到同一目录
COPY *.jar /lzzh.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","/lzzh.jar"]
  1. 使用Docker创建镜像,然后运行即可!
docker build -f DockerFile -t mylzzh:1.0 . 
# 运行
docker run -d -p 8080:8080 mylzzh:1.0

# 后续打开浏览器访问8080即可

你可能感兴趣的:(必备技能,docker,linux,java,编程语言,spring)