Docker学习 基于centOS7

Docker学习 基于centOS7

1. Docker的基本概念

环境说明

  • 采用企业应用广泛的Linux发行版CentOS 7系统
  • 远程连接工具使用Xshell、Xftp

什么是Docker

环境配置的难题

  • 软件开发最大的麻烦事之一,就是环境配置,用户计算机环境各不相同,配置也要根据环境相应变化。
  • 操作系统的设置,各种库和组件的安装。只有它们都正确,软件才能运行,比如开发Java应用,计算机必须配置JDK。
  • 如果某些依赖过时与当前环境不兼容,那更是一场灾难。
  • 将不同的软件集成起来的过程中有很多不可控的风险,由于依赖关系复杂,容易出现兼容性问题。
  • 由于开发、测试、生产环境的差异,一旦需要重新迁移服务器或者重 新部署一套环境,还将重新执行一遍。

如何解决

  • 环境配置如此麻烦,换一台机器,就要重来一次,能不能从根本上解决问题呢
  • 如果软件连同环境一起打包,那就解决了上述问题,也就是说,使用软件时,把原始环境一模一样地复制过来。

Docker如何解决依赖的兼容问题?

  • 将应用的Bins/Libs-与应用一起打包
  • 将每个应用放到一个隔离容器去运行,避免互相干扰

image-20240604193735213

Docker如何解决不同系统环境的问题?

  • Docker将用户程序与所需要调用的系统函数库一起打包
  • Docker在运行到不同操作系统时,直接通过内核创建虚拟的操作系统实例(内核和库),来隔离不同的进程和资源

image-20240604193916337

概念

Docker允许开发中将应用、依赖、函数库、配置-起打包,形成可移植镜像
Docker应用运行在容器中,使用沙箱机制,相互隔离
Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行

Docker的主要用途,目前有三大类。
  • 提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
  • 提供弹性的云服务。因为Docker容器可以随开随关,很适合动态扩容和缩容。
  • 组建微服务架构。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。

Docker与虚拟机

  • 虚拟机(virtual machine)是带环境安装的另一种解决方案,它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。
  • 应用程序对此毫无感知,因为虚拟机看.上去跟真实系统一模一 样,而对于底层.系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。

image-20240604194428346

虽然用户可以通过虚拟机还原软件的原始环境。但是,这个方案有几个缺点。

  • 资源占用多,虚拟机会独占一部分内存和硬盘空间
  • 冗余步骤多虚拟机是完整的操作系统,需要经过繁琐的配置
  • 启动慢,启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。

Docker和虚拟机都是基于软件的平台虚拟化技术,其中:

  • 虚拟机属于完全虚拟化,即模拟完整的底层硬件环境特权指令的执行,客户操作系统无需进行修改。比如我们常用的VirtualBox, VMWare Workstation和Parallels Desktop等虚拟化软件。
  • Docker容器技术是操作系统级虚拟化,即直接通过内核创建虚拟的操作系统实例(内核和库),来隔离不同的进程和资源,多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行。
  • Docker容器不需要额外的虚拟机管理软件和虚拟机操作系统层,直接在宿主机操作系统层面上实现虚拟化,从而达到轻量级,高效的目的。

Docker的组成

Docker包括三个基本概念
  • 镜像 (Image)
  • 容器 (Container)
  • 仓库 (Repository)
  • 理解了这三个概念,就理解了Docker 的整个生命周期。
镜像
  • Docker把应用程序及其依赖,打包在image文件里面。只有通过这个文件,才能生成Docker容器。
  • image文件可以看作是容器的模板,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
  • Docker根据image文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
  • image是二进制文件。实际开发中,一个image文件往往通过继承另一个image文件,加上一些个性化设置而生成。举例来说,你可以在Ubuntu的image基础上,往里面加入Apache服务器,形成你的image.
  • image文件是通用的,一台机器的image文件拷贝到另一台机器, 照样可以使用。一般来说,为了节省时间,我们应该尽量使用别人制作好的image文件,而不是自己制作。即使要定制,也应该基于别人的image文件进行加工,而不是从零开始制作。
  • 为了方便共享,image文件制作完成后,可以上传到网上的仓库。Docker 的官方仓库Docker Hub是最重要、最常用的image仓库。此外,出售自己制作的image文件也是可以的。
容器
  • 镜像(Image) 和容器(Container) 的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
  • 简单的说,容器是独立运行的一个或一-组应用, 以及它们的运行态环境,容器可以被创建、启动、停止、删除、暂停等。
  • 容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户ID空间。
  • 容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作- -样。 这种特性使得容器封装的应用比直接在宿主运行更加安全。
仓库
  • 镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、 分发镜像的服务,Docker Registry就是这样的服务。

  • 一个Docker Registry中可以包含多个仓库(Repository) ; 每个仓库可以包含多个标签(Tag) ;每个标签对应一个镜像。

  • 通常,一个仓库会包含同-个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过**<仓库名>:<标签>**的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest作为默认标签。

  • 以Ubuntu镜像为例,ubuntu是仓库的名字,其内包含有不同的版本标签,如,16.04, 18.04。我们可以通过ubuntu:16.04,或者ubuntu:18.04来具体指定所需哪个版本的镜像。如果忽略了标签,比如ubuntu,那将视为ubuntu:latest。

  • DockerHub: DockerHub是一个Docker镜像的托管平台。 这样的平台称为Docker Registry.

  • 国内也有类似于DockerHub的公开服务,比如网易云镜像服务、阿里云镜像库等。

image-20240604200056898

Docker架构

  • 客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。
  • 服务端(server): Docker守护进程,负责处理Docker指令,管理镜像、容器等。

image-20240604200600639

2. Docker安装与镜像操作

Docker安装

  • Docker分为CE和EE两大版本。CE 即社区版(免费,支持周期7个月)EE即企业版,强调安全,付费使用,支持周期24个月。
  • Docker CE支持64位版本CentOS 7,并且要求内核版本不低于3.10,CentOS 7满足最低内核的要求。
  1. 卸载旧版Docker(可选)

    yum remove docker docker-client  docker-client-latest  docker-common  docker-latest  docker-latest-logrotate  docker-logrotate docker-engine
    
  2. 安装yum工具

    yum install -y yum-utils
    
  3. 镜像配置

    yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  4. 更新软件包索引

    yum makecache fast
    
  5. 下载安装Docker

    yum install docker-ce docker-ce-cli containerd.io
    
  6. 启动Docker

    systemctl start docker
    
  7. 查看Docker版本

    docker version
    
  8. 设置开机自启动Docker服务

    systemctl enable docker.service
    
  9. 镜像加速

    # 进入docker配置的目录
    cd /etc/docker/
    # 创建 daemon.json
    touch daemon.json
    # 编辑这个文件
    vim daemon.json
    # 输入这些内容,其中url改成自己的加速器地址,亦可使用该地址
    {
    	"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"]
    }
    # 加载配置
    systemctl daemon-reload
    # 重启docker服务
    systemctl restart docker
    

镜像操作

镜像名称

  • 一个仓库会包含同-个软件不同版本的镜像
  • 镜像名称-般分两部分组成: [仓库名]:[标签],如果不给出标签,将以latest作为默认标签
  • 如: redis:6.0

镜像操作命令

image-20240604211809151

镜像操作示例

  • 访问DockerHub搜索镜像,https://hub.docker.com/, 搜索redis
  • 拉取镜像: docker pull redis
  • 查看本地镜像: docker images
  • 将镜像导出到磁盘: docker save -0文件名称镜像名称/ID
  • 删除本地镜像: docker rmi镜像名称/ID
  • 导入镜像: . docker load -i文件名称

3. Docker容器操作(比较重要)

Docker容器操作命令

  • docker run 新建并启动容器
  • docker start/stop/pause/uppaues 启动/停止/暂停/恢复容器
  • docker exec 进入容器执行命令
  • docker logs 查看容器运行日志
  • docker ps 查看容器运行状态
  • docker rm 删除指定容器

Nginx与Redis容器示例

Niginx容器示例
  • 拉取nginx镜像 docker pull nginx
  • 创建并启动容器 docker run --name mynginx -d -p 80:80 nginx
  • –name:指定容器名称
  • -p:将宿主机端口与容器端口映射,格式:宿主机端口:容器端口
  • -d:后台运行容器
[root@server ~]# docker run --name mynginx -d -p 80:80 nginx
ef6939316656b697592b95ae6e0c71f5112acc104eec8b796f88fd88fb49e8bf
[root@server ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS                               NAMES
ef6939316656   nginx     "/docker-entrypoint.…"   12 seconds ago   Up 11 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   mynginx
[root@server ~]# 

访问nginx 宿主机 ip:80 (eg:192.168.70.23:80)

192.168.70.23:80

image-20240605092442769

停止容器与启动

docker stop mynginx
[root@server ~]# docker stop mynginx
mynginx
[root@server ~]# docker start mynginx
mynginx
[root@server ~]# 

修改指定端口

// 删除容器之前先将容器停止
[root@server ~]# docker stop mynginx
mynginx
[root@server ~]# docker rm mynginx
mynginx 
[root@server ~]# docker run --name mynginx -d -p 8080:80 nginx
66bc63dbeba824ef8fb0bde7e1f32c785b1ddbe0854fd9d85e2548893e92fc73
[root@server ~]# 
Redis容器示例
  • 拉取redis镜像 docker pull redis
  • 创建并启动容器 docker run --name myredis -d -p 6379:6379 redis
  • 进入容器:docker exec -it myredis bash
  • -it:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互
  • bash:进入容器后执行的命令
  • 进入容器后执行:redis-cli,使用redis客户端操作redis
[root@server ~]# docker run --name myredis -d -p 6379:6379 redis
fbca3d6519e74df81fe0508212e4879ff68a753d5c8002d5af55bee198a6ca66
[root@server ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS                                       NAMES
fbca3d6519e7   redis     "docker-entrypoint.s…"   57 seconds ago   Up 55 seconds   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   myredis
66bc63dbeba8   nginx     "/docker-entrypoint.…"   16 minutes ago   Up 16 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp       mynginx
[root@server ~]# 
//进入容器操作
[root@server ~]# docker exec -it myredis bash
root@fbca3d6519e7:/data# ls
root@fbca3d6519e7:/data# pwd
/data
root@fbca3d6519e7:/data# cd /
root@fbca3d6519e7:/# ls
bin  boot  data  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@fbca3d6519e7:/# redis-cli
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
127.0.0.1:6379> exit
root@fbca3d6519e7:/# exit
exit
[root@server ~]# 

4 Docker数据卷

数据卷基本概念

容器中的数据问题

  • 个容器运行了一段时间,肯定会产生一些数据,比如日志、数据库数据、新改的配置文件等等,如果这些数据文件存放在容器中,当我们删除容器时,这些数据也会被随之删除。
  • 在docker中,提供了一种存储数据的方法,叫做“数据卷”,可以达到数据共享的目的。

我们可以把“数据卷”Data Volumes理解成"宿主机中的目录”,当把某个卷和容器中的某个目录建立映射关系后,就相当于把宿主机中的某个目录和容器中的某个目录建立了映射关系

image-20240605162039910

`数据卷提供了很多有用的特性:

  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
  • 对数据卷的更新不会影响镜像,解耦开应用和数据;
  • 卷会一直存在,直到没有容器使用,可以安全地卸载它。

数据卷操作指令

数据卷操作的基本语法为: docker volume [COMMAND],其中COMMAND可选值:

  • create:创建一个volume;
  • inspect:显示一个或多个volume的信息
  • Is:列出所有的volume
  • prune:删除未使用的volume
  • rm:删除一个或多个指定的volume

数据卷应用案例

  • 创建数据卷:docker volume create testA;
  • 查看数据卷:docker volume ls
  • 查看对于卷的详细信息:docker volume inspect testA
  • 在linux的docker主机中创建一个卷时,其在宿主机对应的目录(挂载点)路径为/var/lib/docker/volumes/卷名/_data
实验
[root@server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED       STATUS       PORTS                                       NAMES
fbca3d6519e7   redis     "docker-entrypoint.s…"   7 hours ago   Up 7 hours   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   myredis
66bc63dbeba8   nginx     "/docker-entrypoint.…"   7 hours ago   Up 7 hours   0.0.0.0:8080->80/tcp, :::8080->80/tcp       mynginx
[root@server ~]# docker volume create testA
testA
[root@server ~]# docker volume ls
DRIVER    VOLUME NAME
local     819bc24f39a076ba9cad018ef5d21057c6167f7f1b725f7a8672146b7badb22b
local     testA
[root@server ~]# 
[root@server ~]# docker volume inspect testA 
[
    {
        "CreatedAt": "2024-06-05T16:36:46+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/testA/_data",
        "Name": "testA",
        "Options": null,
        "Scope": "local"
    }
]
[root@server ~]# 

挂载卷

  • 在创建容器时,可以通过–volume或-v参数挂载一个数据卷到某 个容器目录
  • docker run --name testAcon -V testA:/data -d redis
  • 上述命令表示创建一个名为testAcon的容器 ,将testA卷映射到testAcon容器的/data目录中
  • 注意:如果卷映射的目录在容器中不存在时,会自动在容器中创建对应的目录
  • 一个容器可以使用多个卷,只需要多次使用-v选项指定即可
  • docker run --name testBcon -V testA:/data -V testB:/var/log -d redis
  • 当指定的卷不存在时,docker会自动创建对应的卷,上述命令中的testB数据卷会被自动创建
[root@server ~]# docker run --name testAcon -v testA:/data -d redis
4adb46afd44661b0b5b056d77367078ef634a7ded164fb7cb10cc24fed12f263
[root@server ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS      NAMES
4adb46afd446   redis     "docker-entrypoint.s…"   17 seconds ago   Up 16 seconds   6379/tcp   testAcon
[root@server ~]# 
[root@server ~]# docker exec -it testAcon bash
root@4adb46afd446:/data# ls
root@4adb46afd446:/data# pwd
/data
root@4adb46afd446:/data# ls
a.txt
root@4adb46afd446:/data# echo hell >> a.txt 
root@4adb46afd446:/data# 

复制打开新的终端

[root@server ~]# cd /var/lib/docker/volumes/
[root@server volumes]# ls
819bc24f39a076ba9cad018ef5d21057c6167f7f1b725f7a8672146b7badb22b  backingFsBlockDev  metadata.db  testA
[root@server volumes]# cd testA/_data/
[root@server _data]# ls
[root@server _data]# cat a.txt 
hell
[root@server _data]# 

两个终端都有a.text证明数据已经同步

[root@server _data]# docker run --name testBcon -v testA:/data -v tsetB:/var/log -d redis
444ed6de99c2bdae2c91b01da4537b83125f31aceb54916f3f69132d8a4c5c37
[root@server _data]# ls /var/lib/docker/volumes/
819bc24f39a076ba9cad018ef5d21057c6167f7f1b725f7a8672146b7badb22b  backingFsBlockDev  metadata.db  testA  tsetB
[root@server _data]# 

绑定挂载

  • 前面创建的数据卷都存放在/var/lib/docker/volumes目录中,这个目录是固定的,它们都能被docker volume命令管理。

  • docker还有一种映射宿主机目录的方法,这种方法被称之为”绑定挂载”,绑定挂载能够将指定的宿主机目录挂载到容器中,只需要将卷名替换成宿主机.上的目录路径即可

  • docker run -d --name testAcon -v /root/test1:/data1 redis

  • 上述命令将宿主机的/root/test1目录映射到容器的/data1目录中

  • 绑定挂载不会生成任何卷,它直接将指定的宿主机目录映射到容器中,所以,docker volume命令无法查看或管理到绑定挂载的路径

  • 官方建议使用卷,而不是绑定挂载,但是,绑定挂载有一个优势,就是绑定挂载可以直接将宿主机中的文件(非目录)直接挂载到容器中,比如,将宿主机中的/etc/localtime文件映射到容器中的/etc/localtime文件

  • docker run -d --name testAcon -V /etc/localtime:/etc/localtime alpine

  • 通常,使用绑定挂载就是为了将宿主机中的配置文件挂载到容器中,如果是整个目录的数据,建议使用卷,卷只能映射目录,不能映射文件。

nginx示例
  • 创建容器并挂载数据卷到容器内的HTML目录
  • docker run --name myng -v html:/usrshare/nginx/html -p 80:80 -d nginx
  • 进入html数据卷所在位置,并修改HTML内容
  • cd /var/lib/docker/volumes/html/_data
[root@server ~]# docker start mynginx 
mynginx
[root@server ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS                                   NAMES
444ed6de99c2   redis     "docker-entrypoint.s…"   17 minutes ago   Up 17 minutes   6379/tcp                                testBcon
4adb46afd446   redis     "docker-entrypoint.s…"   27 minutes ago   Up 27 minutes   6379/tcp                                testAcon
66bc63dbeba8   nginx     "/docker-entrypoint.…"   8 hours ago      Up 1 second     0.0.0.0:8080->80/tcp, :::8080->80/tcp   mynginx
[root@server ~]# 
[root@server ~]# docker exec -it mynginx bash
root@66bc63dbeba8:/# cd /usr/share/nginx/html/
root@66bc63dbeba8:/usr/share/nginx/html# ls
50x.html  index.html
root@66bc63dbeba8:/usr/share/nginx/html# cat index.html 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@66bc63dbeba8:/usr/share/nginx/html# 

演示

[root@server ~]# docker run --name myng -v html:/usr/share/nginx/html -p 80:80 -d nginx
36cb2905a4406c2222ced95512970e11e2cbf2ee2107b3f04c4dcebe5681b74f
[root@server ~]# cd /var/lib/docker/volumes/html/_data/
[root@server _data]# ls
50x.html  index.html
[root@server _data]# vim index.html 
[root@server _data]# 
修改
<h1>Welcome to nginx!</h1>	<h1>Welcome to hell!</h1>

image-20240605172635798

5 Docker自定义镜像

镜像的内部结构

​ 对于Docker用户来说,最好的情况是不需要自己创建镜像。几乎所有常用的数据库、中间件、应用软件等都有现成的Docker官 方镜像或其他人和组织创建的镜像,我们只需要稍作配置就可以直接使用。

​ 某些情况下我们也不得不自己构建镜像,比如:

  • 找不到现成的镜像,比如自己开发的应用程序。
  • 需要在镜像中加入特定的功能。

​ 如果只是使用镜像,当然不需要了解镜像的内部结构,直接通过docker命令 下载和运行就可以了,但如果我们想创建自己的镜 像,或者想理解Docker为什么是轻量级的,就非常有必要学习这部分知识了。

  • 下载官方hello-world镜像: docker pull hello-world
  • 运行: docker run hello-world
[root@server _data]# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete 
Digest: sha256:266b191e926f65542fa8daaec01a192c4d292bff79426f47300a046e1bc576fd
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
[root@server _data]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
nginx         latest    4f67c83422ec   6 days ago      188MB
redis         latest    1a83fd5edeed   13 days ago     117MB
hello-world   latest    d2c94e258dcb   13 months ago   13.3kB
[root@server _data]# 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/

[root@server _data]# 

Dockerfile

  • Dockerfile是镜像的描述文件,定义了如何构建Docker镜像, hello-world的
    Dockerfile:
FROM scratch
COPY hello /
CMD [" /hello"]
  • FROM scratch:表示镜像从白手起家,从0开始构建。
  • COPY hello/将文件"hello" 复制到镜像的根目录。
  • CMD[" /hello"]容器启动时,执行/hello。
  • 镜像hello-world中就只有一个可执行文件"hello" ,其功能就是打印出"Hello from Docker …"等信息。

base镜像

  • hello-world虽然是一个完整的镜像,但它并没有什么实际用途。
  • 通常来说,我们希望镜像能提供一 个基本的操作系统环境,用户可以根据需要安装和配置软件。这样的镜像我们称作base镜像。
  • base镜像有两层含义: (1) 不依赖其他镜像,从scratch构建; (2) 其他镜像可以以之为基础进行扩展。
  • 能称作base镜像的通常都是各种Linux发行版的Docker镜像,比如Ubuntu、Debian、CentOS等。
  • 下载CentOS镜像: docker pull centos
[root@server _data]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
a1d0c7532777: Downloading [=================>                                 ]  29.04MB/83.52MB
^C
[root@server _data]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
a1d0c7532777: Pull complete 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
docker.io/library/centos:latest
[root@server _data]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
nginx         latest    4f67c83422ec   6 days ago      188MB
redis         latest    1a83fd5edeed   13 days ago     117MB
hello-world   latest    d2c94e258dcb   13 months ago   13.3kB
centos        latest    5d0da3dc9764   2 years ago     231MB
[root@server _data]# 

为何系统镜像如此之小

​ Linux操作系统由内核空间和用户空间组成

  • 内核空间是kernel, Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。
  • 用户空间的文件系统是rootfs,包含我们熟悉的/dev、/proc、 /bin等目录。
  • 对于base镜像来说,底层直接用Host的kernel,自己只需要提供rootfs就行了。
  • 一个精简的OS, rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他Linux发行版,CentOS的rootfs已经算臃肿的了,alpine还不到10MB。

CentOS的Dockerfile
base镜像提供的是最小安装的Linux发行版,CentOS镜像的Dockerfile的内容

FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
CMD ["/bin/bash"]
  • ADD指令添加到镜像的tar包就是CentOS 7的rootfs。在制作镜像时,这个tar包会自动解压到/目录下,生成/dev、/proc、 /bin等目录。
  • 可在Docker Hub的镜像描述页面中查看Dockerfile.\

Docker支持运行多种Linux OS

  • 不同Linux发行版的区别主要就是rootfs。
  • 比如Ubuntu 14.04使用upstart管理服务,apt管理软件包;而CentOS 7使用systemd和yum。这些都是用户空间上的区别,Linux kernel差别不大。
  • 所以Docker可以同时支持多种Linux镜像,模拟出多种操作系统环境。
  • Debian和BusyBox(一种嵌入式Linux)上层提供各自的rootfs,底层共用Docker Host的kernel。

image-20240605180537143

通过Dockerfile构建镜像

构建镜像

FROM指定基础镜像FROM centos:6
NVE设置环境变量,可在后面指定作用ENV key value
COPY拷贝本地文件到镜像的指定目录COPY ./mysql-8.7rpm /tmp
RUN执行Linux的shell命令,一般是安装过程的命令RUN yum install gcc
EXPOSE指定容器运行时监听的端口,是给镜像使用者看的EXPOSE 8080
ENTRYPOINT镜像中应用的启动命令,容器运行时调用ENTRYPOINT java -jar xx.jar

一、基于Centos基础镜像构建Java应用镜像

1. 上传JDK

创建文件夹,将jdk安装包上传到该目录下

mkdir -p /root/dockerfile/java
2. 编写dockerfile

在/root/dockerfile/java目录下创建文件dockerfile_java,内容如下:

FROM centos:7  
  
# 配置环境变量,JDK的安装目录  
ENV JAVA_DIR=/usr/local  
  
# 拷贝jdk和java项目的包  
COPY ./jdk-8u171-linux-x64.tar.gz $JAVA_DIR/  
COPY ./demo-0.0.1-SNAPSHOT.jar /tmp/app.jar  
  
# 安装JDK  
RUN cd $JAVA_DIR \  
  && tar -xf ./jdk-8u171-linux-x64.tar.gz \  
  && mv ./jdk1.8.0_171 ./java8  
  
# 配置环境变量  
ENV JAVA_HOME=$JAVA_DIR/java8  
ENV PATH=$PATH:$JAVA_HOME/bin  
  
# 暴露端口  
EXPOSE 8080  
# 入口,java项目的启动命令  
ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]
3. 生成镜像
#docker build -f 文件名 -t 镜像名 .代表当前目录
docker build -f dockerfile_java -t myjava:1.0 .
4. 验证镜像是否生成成功
[root@server java]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
myjava        1.0       964df2decf1e   2 minutes ago   836MB
nginx         latest    4f67c83422ec   6 days ago      188MB
redis         latest    1a83fd5edeed   13 days ago     117MB
hello-world   latest    d2c94e258dcb   13 months ago   13.3kB
centos        latest    5d0da3dc9764   2 years ago     231MB
[root@server java]# 
5. 启动容器
[root@server java]# docker run --name myjava -d -p 8020:8080 myjava:1.0 
143e26858f29e371a7740fc9024a1de791a887315a0a0bc7a09750932f4c6d81
[root@server java]# 

二、通过Java镜像构建应用镜像

1. 编写dockerfile

在/root/dockerfile/java目录下创建文件dockerfile_java2,内容如下:

FROM openjdk:8-alpine  
COPY ./demo-0.0.1-SNAPSHOT.jar /tmp/app.jar  
# 暴露端口    
EXPOSE 8080    
# 入口,java项目的启动命令    
ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]
2. 生成镜像
#docker build -f 文件名 -t 镜像名 .代表当前目录
docker build -f dockerfile_java2 -t myjava:2.0 .
3. 验证镜像是否生成成功
[root@server java]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
myjava        2.0       1e0641859ffb   39 seconds ago   158MB
myjava        1.0       964df2decf1e   33 minutes ago   836MB
nginx         latest    4f67c83422ec   6 days ago       188MB
redis         latest    1a83fd5edeed   13 days ago      117MB
hello-world   latest    d2c94e258dcb   13 months ago    13.3kB
centos        latest    5d0da3dc9764   2 years ago      231MB
[root@server java]# 
4. 启动容器
[root@server java]# docker run --name myjava2 -d -p 8081:8080 myjava:2.0 
4d3961be3a62680b08c0a4447dc5fe1f527b83a6d516fe9c96ce873eba9ea040
[root@server java]# 
  • 55
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
1. 安装DockerCentOS上安装Docker,可以使用官方的安装脚本。打开终端并运行以下命令: ``` $ curl -fsSL https://get.docker.com/ | sh ``` 如果您的系统上没有curl,请先安装它: ``` $ yum install curl ``` 2. 下载PostgreSQL的Dockerfile 我们可以从官方的Docker Hub上下载PostgreSQL的Dockerfile。使用以下命令: ``` $ curl -O https://raw.githubusercontent.com/docker-library/postgres/master/13/alpine/Dockerfile ``` 3. 编辑Dockerfile 使用vim或nano等编辑器打开下载下来的Dockerfile文件,进行以下配置: ``` FROM centos:latest ENV POSTGRES_USER postgres ENV POSTGRES_PASSWORD postgres ENV POSTGRES_DB postgres RUN yum update -y && \ yum install -y postgresql-server postgresql-contrib && \ yum clean all USER postgres RUN initdb --encoding=UTF8 --locale=C -D /var/lib/pgsql/data && \ pg_ctl -D /var/lib/pgsql/data -l logfile start && \ psql --command "CREATE USER postgres WITH SUPERUSER PASSWORD 'postgres';" && \ createdb -O postgres postgres VOLUME ["/var/lib/pgsql/data"] EXPOSE 5432 CMD ["postgres", "-D", "/var/lib/pgsql/data", "-c", "config_file=/var/lib/pgsql/data/postgresql.conf"] ``` 4. 构建Docker镜像 使用以下命令构建Docker镜像: ``` $ docker build -t my_postgresql . ``` 这将构建一个名为“my_postgresql”的新Docker镜像。 5. 运行PostgreSQL容器 使用以下命令运行PostgreSQL容器: ``` $ docker run -d -p 5432:5432 --name my_postgresql_container my_postgresql ``` 这将创建一个名为“my_postgresql_container”的新容器,并将容器的端口5432映射到主机的端口5432。 6. 测试PostgreSQL容器 为了测试新的PostgreSQL容器,请使用以下命令: ``` $ psql -h localhost -U postgres -d postgres ``` 您应该现在可以通过psql连接到PostgreSQL容器。 现在您已经成功地使用Docker创建了一个基于CentOS的PostgreSQL镜像,并运行了一个新的PostgreSQL容器。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值