Docker学习

一、Docker概述

参考文章:https://www.kuangstudy.com/bbs/1552836707509223426

1.Docker为什么出现

在服务器中配置环境十分麻烦,无法跨平台。例如在Windows开发,最后到Linux部署:

  • 传统:开发jar,运行和部署由运维来做。
  • 现在:开发打包部署上线都由开发来完成。

Docker给以上问题提供了解决方案

Docker的思想来源自集装箱,将每个项目打包装箱,每个箱子是相互隔离的

2.Docker的历史

2010年,几个搞IT的年轻人,就在美国成立了一家公司dotcloud做一些pass的云计算服务!
LXC有关的容器技术!他们将自己的技术(容器化技术)命名就是Docker!
Docker刚刚诞生的时候,没有引起行业的注意!(dotCloud就活不下去)
开源(开放源代码)
2013年,Docker开源!
Docker越来越多的人发现了docker的优点!就火了,Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布!
Docker为什么这么火?十分的轻巧
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一台或者多台电脑!(很笨重)
虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术。

Vm:隔离,需要开启多个虚拟机,安装和启动非常耗时


docker:隔离,镜像都十分小巧,大大节省了安装运行所需的时间和空间

Docker是基于Go语言开发的!开源项目!

官网:https://www.docker.com/

文档地址:https://docs.docker.com/

Doker镜像仓库地址:https://hub.docker.com/

3.Docker能做什么

1.容器化技术

比较Docker和虚拟机技术的不同:

  • 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件。
  • 容器内的应用直接运行在宿主机的内核中,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了。
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响。

2.Devops(开发和运维)

应用更快速的交付和部署

更便捷的升级和扩缩容

更简单的系统运维

更高效的计算资源利用

二、Docker安装

1.Docker的基本组成

img

镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像=>run>tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

容器(container):
Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。
启动,停止,删除,基本命令!
目前就可以把这个容器理解为就是一个简易的linux系统

仓库(repository):
仓库就是存放镜像的地方!
仓库分为公有仓库和私有仓库!
Docker Hub(默认是国外的)阿里云.…都有容器服务器(配置镜像加速!)

2.安装Docker

linux安装Docker

安装环境:

注意:之前使用的CentOS8由于停止维护了,这意味着无法再使用新版本的软件包更新了,Docker 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10,所以推荐使用CentOS7

# 查看内核版本:
uname -r
# 5.10.16.3-microsoft-standard-WSL2

# 确保yum包更新到最新:
yum -y update

# 卸载旧版本(如果安装过旧版本):
sudo yum remove -y docker*

# 一键安装
yum install -y docker

# 启动docker
sudo systemctl start docker

# 设置开机自启动
sudo systemctl enable docker

# 查看版本信息
docker version

# 测试hello-world
docker run hello-world

image-20230112175354780

阿里云镜像加速:

  1. 登录阿里云,找到容器服务。
  2. 找到镜像加速地址。
  3. 配置使用:四个命令,依次执行即可
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxx.xxx.xxx.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

WSL2安装Docker

如果没钱买云服务器(比如我)又觉得虚拟机太麻烦,可以试试微软的WSL(适用于Windows的Linux子系统)。

官方教程:适用于 Linux 的 Windows 子系统文档 | Microsoft Learn

docker安装:WSL 上的 Docker 容器入门 | Microsoft Learn

wsl2安装CentOS(推荐使用CentOS7):

镜像下载地址:https://github.com/wsldl-pg/CentWSL/releases

下载解压zip,点击exe文件等他安装,安装完成后再次点击exe文件即可进入linux终端

三、Docker常用命令

1.帮助命令

docker version        # 显示docker的版本信息
docker info              # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help         # 帮助命令

帮助文档地址:https://docs.docker.com/reference/

2.镜像命令

docker images

查看所有本地主机上的镜像

[root@DESKTOP-CKI6M6S ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   15 months ago   13.3kB
#解释
REPOSITORY    	镜像的仓库源
TAG            	镜像的标签
IMAGE ID    	镜像的id
CREATED        	镜像的创建时间
SIZE        	镜像的大小
# 命令参数可选项
 -a, --all         # 显示所有镜像 (docker images -a)
 -q, --quiet       # 仅显示镜像id (docker images -q)

docker search

搜索镜像

[root@DESKTOP-CKI6M6S ~]# docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   13683     [OK]
mariadb                         MariaDB Server is a high performing open sou…   5226      [OK]
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   721       [OK]

# 命令参数可选项 (通过搜索来过滤)
--filter=STARS=3000     # 搜索出来的镜像就是stars大于3000的

docker pull

下载镜像

# 下载镜像:docker pull 镜像名[:tag]
[root@DESKTOP-CKI6M6S ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8740c948ffd4: Pull complete
d2c0556a17c5: Pull complete
c8b9881f2c6a: Pull complete
693c3ffa8f43: Pull complete
8316c5e80e6d: Pull complete
b2fe3577faa4: Pull complete
Digest: sha256:b8f2383a95879e1ae064940d9a200f67a6c79e710ed82ac42263397367e7cc4e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest  # 本机地址

docker rmi

删除镜像

[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f 镜像id                    # 删除指定的镜像
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f 镜像id 镜像id 镜像id    # 删除多个镜像(空格分隔)
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker rmi -f $(docker images -aq)    # 递归删除全部的镜像

3.容器命令

我们下载了镜像就可以创建容器了,下面通过nginx进行测试学习。

新建容器并启动

docker run [可选参数] image
# 参数说明
--name="name"        容器名字:用来区分容器
-d                    后台方式运行:相当于nohup
-it                    使用交互式运行:进入容器查看内容
-p                    指定容器的端口(四种方式)小写字母p
    -p ip:主机端口:容器端口
    -p 主机端口:容器端口
    -p 容器端口
    容器端口
-P                     随机指定端口(大写字母P)

#测试后台启动nginx并将容器80端口映射到主机的8180端口,浏览器访问
[root@DESKTOP-CKI6M6S ~]# docker run -d -p 8180:80 --name nginx01 nginx
32c9d36262b30fe95851981b1dcddf8531ce5631e6e4c4197348085a19bc8755

浏览器访问localhost:8180,成功访问nginx。

image-20230112184126329

启动容器后进入容器

[root@DESKTOP-CKI6M6S ~]# docker run -it --name nginx01 nginx /bin/bash
root@0eff463ef7fd:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx

# 退出容器
# exit:退出容器并停止容器运行
# ctrl+p+q:退出容器但不停止容器运行

列出所有运行的容器

docker ps    # 列出当前正在运行的容器
# 命令参数可选项
-a        # 列出当前正在运行的容器+历史运行过的容器
-n=?    # 显示最近创建的容器(可以指定显示几条,比如-n=1)
-q        # 只显示容器的编号

删除容器

docker rm 容器id  # 删除容器(不能删除正在运行的容器)如果要强制删除:docker rm -f 容器id
docker rm -f $(docker ps -aq)        # 删除全部容器

启动和停止容器

docker start 容器id        # 启动容器
docker restart 容器id    # 重启容器
docker stop 容器id        # 停止当前正在运行的容器
docker kill 容器id        # 强制停止当前容器

4.常用的命令

后台启动容器

# 命令docker run -d 镜像名
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -d centos
# 问题:docker ps发现centos停止了
# 常见的坑:docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止。
# 比如:nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

查看日志

docker logs -tf --tail 容器id
# 自己编写一段shell脚本
docker run -d centos /bin/sh -c "while true;do echo kuangshen;sleep 1;done"
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker logs -tf  容器id
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker logs -tf --tail 10  容器id
# 显示日志
-tf                        # 显示日志
--tail number    # 要显示的日志条数

查看容器中进程的信息

[root@DESKTOP-CKI6M6S ~]# docker top 0eff463ef7fd
UID		PID		PPID	C		STIME		TTY		TIME		CMD
root	3885	3864	0		10:43		?		00:00:00	/bin/bash

查看镜像的元数据

# 命令docker inspect 容器id

进入当前正在运行的容器

# 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 命令
# 方式一
docker exec -it 容器id /bin/bash
# 方式二
docker attach 容器id

# docker exec        # 进入容器后开启一个新的终端,可以再里面操作(常用)
# docker attach        # 进入容器正在执行的终端,不会启动新的进程。

从容器内拷贝文件到主机上

docker cp 容器id:容器内路径 目的主机的路径
# 拷贝是一个手动过程,未来我们使用 -v 卷的技术,可以实现,自动同步(容器内的/home路径和主机上的/home路径打通)

5.可视化

portainer

Docker图形化管理工具,提供一个后台面板供我们操作!

#启动运行
docker run -d -p 8088:9000 --restart=always -v
/var/run/docker.sock:/var/run/docker.sock --privileged=true

访问测试:http://ip:8088

img

选择local:

img

进入后的面板:

img

四、Docker镜像讲解

1. 镜像是什么

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

如何得到镜像:

  • 从远程仓库下载
  • 其他人拷贝给你
  • 自己制作一个镜像DockerFile

2. Docker镜像加速原理

UnionFS(联合文件系统)

我们下载的时候看到的一层层就是这个!
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

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

Docker镜像加载原型

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

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

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

img

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

img

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。
由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
(虚拟机是分钟级,容器是秒级!)

3. 分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过 docker image inspect命令!

4. commit镜像

# 提交容器成为一个新的副本
docker commit
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

五、容器数据卷

1. 什么是容器数据卷

将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!(需求:数据可以持久化)
MySQL,容器删了,删库跑路!(需求:MySQL数据可以存储在本地)
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux主机上面!

2. 使用数据卷

直接使用命令来挂载:-v

docker run -it -v 主机目录:容器内目录 镜像名 /bin/bash
# 测试,查看容器信息
docker inspect 容器id

img

3. 实战:安装mysql

# 获取镜像
docker pull mysql:5.7
# 运行容器,需要做数据目录挂载。(安装启动mysql,注意:需要配置密码)
# 官方启动mysql
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 我们启动mysql(-e是环境配置)
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -d -p 7777:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 启动成功之后,我们在本地使用navicat来接测试一下。
# navicat连接到服务器的7777端口和容器内的3306映射,这个时候我们就可以连接上了!
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!(OK的)

如果我们将容器删除:发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

4. 匿名和具名挂载

# 匿名挂载
docker run -d -p --name nginx01 -v /etc/nginx nginx
# 查看所有的volume的情况
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     964b8e505f12f65fb23fd21f05cfa9ecd6c2c6b2ca89c0e44f168bb017dfabd6
# 这种就是匿名挂载:我们在-v挂载目录时,只写了容器内的路径,没有写容器外的路径。
# 具名挂载
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker run -d -p 3344:80 --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     964b8e505f12f65fb23fd21f05cfa9ecd6c2c6b2ca89c0e44f168bb017dfabd6
local     juming-nginx
# 通过 -v 卷名:容器内的路径(具名挂载)
# 查看一下这个卷

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data"(xxxx是卷名)
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载

# 如何确定是具名挂载,还是匿名挂载,还是指定路径挂载
-v 容器内的路径                # 匿名挂载
-v 卷名:容器内的路径        # 具名挂载
-v /宿主机路径:容器内路径    # 指定路径挂载

六、DockerFile

1. DockerFile介绍

dockerfile是用来构建docker镜像的文件!命令参数脚本!
构建步骤:
1、编写一个dockerfile文件
2、docker build 构建成为一个镜像
3、docker run运行镜像
4、docker push发布镜像(DockerHub、阿里云镜像仓库!)

2. DockerFile的构建过程

基础知识

1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、# 表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交!

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为企业交付的标准,必须要掌握!
步骤:开发,部署,运维。。。缺一不可!|
DockerFile:构建文件,定义了一切的步骤,源代码。
Dockerlmages:通过DockerFile构建生成的镜像,最终发布和运行的产品。
Docker容器:容器就是镜像运行起来提供服务的。

3. DockerFile的命令

以前的话我们就是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!

FROM        	# 基础镜像,一切从这里开始构建
MAINTAINER    	# 镜像是谁写的:姓名+邮箱
RUN            	# 镜像构建的时候需要运行的命令
ADD           	# 步骤:tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR        	# 镜像的工作目录
VOLUME        	# 挂载的目录
EXPOSE        	# 暴露端口配置
CMD            	# 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT    	# 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD        	# 当构建一个被继承DockerFile这个时候就会运行ONBUILD的指令。触发指令。
COPY        	# 类似ADD,将我们文件拷贝到镜像中
ENV            	# 构建的时候设置环境变量!

CMD和ENTRYPOINT区别

CMD            # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT     # 指定这个容器启动的时候要运行的命令,可以追加命令

4. 制作tomcat镜像

  1. 准备镜像文件:tomcat压缩包,jdk的压缩包!

  2. 编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,就不需要-f指定文件名了!

     FROM centos:7
     MAINTAINER sywl<xxxx@qq.com>
     COPY readme.txt /usr/local/readme.txt
     ADD jdk-8u271-linux-x64.tar.gz /usr/local/
     ADD apache-tomcat-9.0.5.tar.gz /usr/local/
     RUN yum -y install vim
     ENV MYPATH /usr/local
     WORKDIR $MYPATH
     ENV JAVA_HOME /usr/local/jdk1.8.0_271
     ENV CLASS_PATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
     ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.5
     ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.5
     ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
     EXPOSE 8080
     CMD /usr/local/apache-tomcat-9.0.5/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.5/bin/logs/catalina.out
    
  3. 构建镜像

    docker build --name diytomcat .
    
  4. 启动镜像

    [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker run -d -p 3355:8080 --name sywltomcat -v /home/sywl/build/tomcat/test:/usr/local/apache-tomcat-9.0.5/webapps/test -v /home/sywl/build/tomcat/tomcatlog:/usr/local/apache-tomcat-9.0.5/logs diytomcat
    
  5. 访问测试

  6. 发布项目(可直接发布在宿主机test文件夹下)

    # /home/sywl/build/tomcat/test/WEB-INF/web.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
     version="2.5">
    </web-app>
    
    # /home/sywl/build/tomcat/test/index.jsp文件
    <%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>hello,sywl</title>
    </head>
    <body>
    Hello World!<br/>
    <%
    System.out.println("----my web test----");
    %>
    </body>
    </html>
    

    发现:项目部署成功,可以直接访问ok!(ip地址:3355/test)
    我们以后开发的步骤:需要掌握Dokcerfile的编写!我们之后的一切都是使用docker镜像来发布运行!

5. 发布自己的镜像

  1. https://hub.docker.com/ 注册自己的账号
  2. 确定这个账号可以登录
  3. 在我们服务器上提交自己的镜像
 [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker login --help
 Usage:  docker login [OPTIONS] [SERVER]
 Log in to a Docker registry.
 If no server is specified, the default is defined by the daemon.
 Options:
   -p, --password string   Password
       --password-stdin    Take the password from stdin
   -u, --username string   Username
  1. 登录完毕后就可以提交镜像了,就是一步: docker push
 # 登录命令
 [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker login -u xxxx
 Password:
 WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
 Configure a credential helper to remove this warning. See
 https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 Login Succeeded
 # push镜像出现的问题?
 [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker push sunyiwenlong/diytomcat
 The push refers to repository [docker.io/sunyiwenlong/diytomcat]
 An image does not exist locally with the tag: sunyiwenlong/diytomcat
 # 解决,增加一个tag
 [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker tag 6a5eb12e1252 账号id/tomcat:1.0
 # docker push即可;自己发布的镜像尽量带上版本号
 [root@iZbp13qr3mm4ucsjumrlgqZ tomcat]# docker push 账号id/tomcat:1.0
posted @ 2023-01-13 15:58  Abduu  阅读(50)  评论(0)    收藏  举报