Docker学习笔记


前言

因为项目需要,在此学习一下docker相关知识,本篇参考黑马程序员相关课程以及其他人博客总结而成。

一、Docker基本概念

1. Docker对比与传统虚拟机的优势

在这里插入图片描述

2.Docker的三个基本概念

在这里插入图片描述
上图基本罗列了Docker的一些相关操作,其中有三个名词:

  • Image(镜像):将软件环境打包好的模板,用来创建容器,一个镜像可以创建N个容器
  • Container(容器):镜像运行后产生的实例称为容器,每运行一次镜像就会产生一个容器,容器之间相互是隔离的。
  • Repository(仓库):用来保存镜像,仓库中含有许多的镜像,每个镜像都有不同的标签tag。

二、Docker本身的一些命令以及如何配置镜像源

2.1 启动Docker并查看状态

  • docker version #查看docker版本
  • systemctl start docker #启动docker
  • systemctl stop docker #停止docker
  • systemctl status docker #查看状态
  • systemctl restart docker #重启
  • systemctl enable docker #设置开机自动启动

2.2 配置国内镜像源

阿里镜像源:

mkdir -p /etc/docker
vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://duvzla6d.mirror.aliyuncs.com"]
}

systemctl daemon-reload
systemctl restart docker

其他镜像源:跳转

三、Docker常用命令

下图为Docker常用命令示意图,可以看出基本是基本是围绕着容器、镜像、仓库、DockFile等。
在这里插入图片描述
更多命令 可参考:https://docs.docker.com/engine/reference/commandline/cli/
注:忘记用法的命令都可以通过最后加–help的方式查看用法。

3.1 镜像相关命令

操作命令说明
查找docker search 关键字在docker hub网站查看镜像详情
抽取docker pull 镜像名:Tag如果Tag不指定,默认是latest 即最新版
推送docker push NAME[:TAG]把指定镜像推送到远程仓库
镜像保存docker save保存镜像到本地压缩文件
镜像加载docker load从本地压缩文件加载镜像
列表docker images查看本地所有镜像
获取元信息docker inspect 镜像ID或镜像名:Tag获取有关该镜像的相关信息
删除docker rmi -f 镜像id或镜像名:Tag删除本地镜像,-f强制删除
DockerFile构建镜像docker build -f Dockerfile文件的路径 -t 镜像名:tag 命令执行的上下文利用DockerFile自己构建镜像

3.2 容器相关操作

操作命令说明
运行docker run -name 容器名 -p 宿主机端口:容器端口 -d -v 数据卷名或者宿主文件夹路径:容器内文件夹路径 -it 镜像id或镜像名:版本号-name:指定容器名,如果不指定会随机命名
-i 以交互模式运行
-t 分配一个终端 通常一起使用-it
-p指定端口映射
-d 表示后台运行,以服务方式运行
-v 指定挂载
容器列表docker ps -a -q-a:查看所有容器(包括已关闭的)
-q 只显示容器id
启动容器docker start 容器id/容器名如果该容器已停止 通过该命令可以启动
重新启动容器docker restart 容器id/容器名如果该容器在运行,通过该命令能让其重启
关闭容器docker stop 容器id/容器名关闭指定容器
删除容器docker rm -f 容器id/容器名-f 表示强制删除容器(可删除正在运行的容器)
日志docker logs 容器id/容器名获取容器日志
获取容器元信息docker inspect 容器id/容器名获取容器元信息
进入容器docker exec -it 容器id/容器名 bash或者/bin/bash以交互模式进入一个正在运行的容器
拷贝文件docker cp 主机中的文件路径 容器id/容器名:容器路径
docker cp 容器id或容器名称:容器路径 主机中的文件
谁在前 从谁那里拷贝
把容器保存为镜像docker commit 容器 镜像:Tag把修改的容器保存为新的镜像

四、Docker 的分层

Docker 的分层结构是 Docker 镜像的核心概念之一,它使得 Docker 在创建和管理容器时变得高效、灵活且资源节约。

在 Docker 中,每个镜像都由一系列分层(Layers)组成,这些分层是只读的文件系统。每一层都包含了镜像的一部分文件系统内容或配置。当你创建一个新的镜像时,Docker 将会基于现有的镜像,添加一个新的分层。这种方式可以极大地节省存储空间,因为多个镜像可以共享相同的分层。

以下是 Docker 分层结构的一些关键概念:

  1. 基础镜像(Base Images):基础镜像是 Docker 镜像的起点,它包含了操作系统的基本文件系统和工具。比如,Ubuntu、Alpine Linux、CentOS 等都可以作为基础镜像。基础镜像是只读的,且通常包含操作系统的核心组件。

  2. 分层(Layers):每个镜像由一系列分层组成,每一层都包含了文件系统的一部分。这些分层是只读的,并且通过联合文件系统(Union File System)进行组合,形成一个完整的镜像。当容器运行时,这些分层被叠加在一起,为容器提供文件系统和环境。

  3. 联合文件系统(Union File System):联合文件系统是一种文件系统的组合方式,它允许将多个文件系统挂载到同一个目录下,使得这些文件系统的内容在逻辑上呈现为单个文件系统。Docker 使用联合文件系统将多个镜像的分层组合成一个容器的文件系统。

  4. 镜像的可读性和写时复制(Copy-on-Write):由于 Docker 分层的特性,当容器运行时,它们可以读取所有镜像的分层,但是只有在容器中进行的修改才会写入新的分层中。这种写时复制的机制使得容器的创建和修改变得高效,并且可以节省存储空间。

  5. 镜像标签(Image Tags):镜像标签是用于标识镜像版本的字符串,它通常包含了镜像的名称和版本号。通过使用不同的标签,可以方便地管理和区分不同版本的镜像。

总的来说,Docker 的分层结构使得容器的创建、共享和管理变得更加灵活和高效。通过共享相同的基础镜像和分层,可以大大减少存储空间的占用,并且能够快速地创建、启动和销毁容器。

五、DockerFile

由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。
而这种记录镜像结构的文件就称为Dockerfile,其对应的语法可以参考官方文档:
https://docs.docker.com/engine/reference/builder/

在这里插入图片描述
例如,要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]

当然我们也可以直接把基础镜像设为JDK环境。

# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]

六、 Docker网络机制

一个Java项目的容器,而Java项目往往需要访问其它各种中间件,例如MySQL、Redis等。一个Docker中的所有容器都是可以通过本地IP互联的,因为他们都在同一个虚拟网关(docker0)下.

但是,容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。

所以,我们必须借助于docker的网络功能来解决这个问题,官方文档:
https://docs.docker.com/engine/reference/commandline/network/
常见命令有:
在这里插入图片描述

案例:

# 1.首先通过命令创建一个网络
docker network create hmall

# 2.然后查看网络
docker network ls
# 结果:
NETWORK ID     NAME      DRIVER    SCOPE
639bc44d0a87   bridge    bridge    local
403f16ec62a2   hmall     bridge    local
0dc0f72a0fbb   host      host      local
cd8d3e8df47b   none      null      local
# 其中,除了hmall以外,其它都是默认的网络

# 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
# 这样该网络内的其它容器可以用别名互相访问!
# 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db
# 3.2.db容器,也就是我们的java项目
docker network connect hmall dd

# 4.进入dd容器,尝试利用别名访问db
# 4.1.进入容器
docker exec -it dd bash
# 4.2.用db别名访问
ping db
# 结果
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms
# 4.3.用容器名访问
ping mysql
# 结果:
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms

总结:

  • 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
  • 在同一个自定义网络中的容器,可以通过别名互相访问

七、 项目部署实战

7.1 部署Java项目

具体参考如下链接 实现Java mysql nginx项目的部署。
https://b11et3un53m.feishu.cn/wiki/MWQIw4Zvhil0I5ktPHwcoqZdnec

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值