Docker总结

Docker

什么是Docker

Docker是基于Go语言实现的云开源项目。

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

Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在 Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

Docker安装

基本构成

镜像(image):

Docker镜像(Image)就是一个只读的模板。
镜像可以用来创建 Docker容器,一个镜像可以创建很多容器。
就好似Java中的类和对象,类就是镜像,容器就是对象!

容器(container):

Docker利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。
可以把容器看做是一个简易版的Linux 环境(包括root用户权限、
进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,
唯一区别在于容器的最上面那一层是可读可写的。

仓库(repository):

仓库(Repository)是集中存放镜像文件的场所。 仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。 国内的公开仓库包括阿里云 、网易云等

总结:

  • Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个 可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生 成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。 同一个 image 文件,可以生成多个同时运行的容器实例。
  • image 文件生成的容器实例,本身也是一个文件,称为镜像文件
  • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例, 也就是我们的容器
  • 至于仓库,就是放了一堆镜像的地方,我们可以把镜像发布到仓库中,需要的时候从仓库中拉下来就可以了。

安装环境

建议安装在linux系统上,通过uname -r来查看本机的架构信息,或使用cat /etc/os-release查看系统版本等信息。

官网安装参考手册:https://docs.docker.com/engine/install/centos/

安装卸载步骤

  1. yum安装gcc相关环境

    yum -y install gcc
    yum -yin stall gcc-c++
    
  2. 写在老旧版本

    yum remove docker \
                      docker-client \
                      docker-client-latest \
                      docker-common \
                      docker-latest \
                      docker-latest-logrotate \
                      docker-logrotate \
                      docker-engine
    
  3. 安装需要的软件包

    yuminstall-yyum-utils
    
  4. 设置仓库镜像

    # 错误
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 
    ## 报错
    [Errno 14] curl#35 - TCP connection reset by peer
    [Errno 12] curl#35 - Timeout
    # 正确推荐使用国内的
    yum-config-manager --add-repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker-ce.repo
    
  5. 更新yum软件包索引

    yum makecache fast
    
  6. 安装 Docker CE

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

systemctl start docker
  1. 命令测试

    docker version
    docker run hello-world
    docker images
    
  2. 卸载

    systemctl stop docker
    
    yum -y remove docker-ce docker-ce-cli containerd.io
    
    rm -rf /var/lib/docker
    

可配置aliyun镜像加速

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://qiyb9988.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

Docker常用命令

帮助命令

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

镜像命令

docker images

~ » docker images    # 列出本地主机上的镜像 

REPOSITORY                  TAG       IMAGE ID       CREATED        SIZE
docker101tutorial           latest    f925f4719971   6 hours ago    28.2MB
pzym321/docker101tutorial   latest    f925f4719971   6 hours ago    28.2MB
docker/getting-started      latest    083d7564d904   2 months ago   28MB

# 解释
REPOSITORY 镜像的仓库源 
TAG 镜像的标签 
IMAGE ID 镜像的ID 
CREATED 镜像创建时间 
SIZE 镜像大小

# 同一个仓库源可以有多个TAG,代表这个仓库源的不同版本,我们使用REPOSITORY:TAG 定义不同的镜像,如果你不定义镜像的标签版本,docker将默认使用 lastest 镜像!

# 可选项
-a: 列出本地所有镜像 
-q: 只显示镜像id 
--digests: 显示镜像的摘要信息

docker search

# 搜索镜像
~ » docker search redis                                                             
NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
redis                            Redis is an open source key-value store that…   9881      [OK]

# docker search 某个镜像的名称 对应DockerHub仓库中的镜像
# 可选项
--filter=stars=5000 : 列出收藏数不小于指定值的镜像。

~ » docker search redis --filter=stars=5000 

NAME      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
redis     Redis is an open source key-value store that…   9881      [OK]

docker pull

# 下载镜像
~ » docker pull mysql                                                               
Using default tag: latest # 不写tag,默认是latest
latest: Pulling from library/mysql
a330b6cecb98: Pull complete
9c8f656c32b8: Pull complete
88e473c3f553: Pull complete
062463ea5d2f: Pull complete
daf7e3bdf4b6: Pull complete
1839c0b7aac9: Pull complete
cf0a0cfee6d0: Pull complete
1b42041bb11e: Pull complete
10459d86c7e6: Pull complete
b7199599d5f9: Pull complete
1d6f51e17d45: Pull complete
50e0789bacad: Pull complete
Digest: sha256:99e0989e7e3797cfbdb8d51a19d32c8d286dd8862794d01a547651a896bcf00c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实位置

# 等价于 docker pull docker.io/library/mysql:latest
-------------------------------------------------------------------------------------------------
~ » docker pull mysql:5.7  # 写版本的                                                        
...

docker rmi

# 删除镜像
docker rmi -f 镜像id # 删除单个
docker rmi -f 镜像名:tag 镜像名:tag # 删除多个
docker rmi -f $(docker images -qa)   # 删除全部

容器命令

说明:有镜像才能创建容器,我们这里使用 centos 的镜像来测试,就是虚拟一个 centos !

新建容器并启动

# 命令
docker run [OPTIONS] IMAGE [COMMAND][ARG...]
# 常用参数说明 
--name="Name" # 给容器指定一个名字
-d # 后台方式运行容器,并返回容器的id!
-i # 以交互模式运行容器(即使没有连接,也要保持标准输入保持打开状态),通过和 -t 一起使用
-t # 给容器重新分配一个终端,通常和 -i 一起使用
-P # 随机端口映射(大写)
-p # 指定端口映射(小结),一般可以有四种写法
      ip:hostPort:containerPort 
      ip::containerPort 
      hostPort:containerPort (常用) 
      containerPort
      
#  不懂就参考博客
# https://blog.csdn.net/claram/article/details/104228727?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.essearch_pc_relevant&spm=1001.2101.3001.4242

# 测试
# 使用centos进行用交互模式启动容器,在容器内执行/bin/bash命令!
~ » docker run -it centos /bin/bash #默认的就是/bin/bash,所以可以不写,也可使用/bin/sh

列出所有运行的容器

# 命令
docker ps [OPTIONS]

# 常用参数说明
-a # 列出当前所有正在运行的容器 + 历史运行过的容器
-l # 显示最近创建的容器
-n=? # 显示最近n个创建的容器
-q # 静默模式,只显示容器编号。

退出容器

exit # 容器停止退出
ctrl+P+Q # 容器不停止退出

启动停止容器

docker start (容器id or 容器名)   # 启动容器
docker restart (容器id or 容器名) # 重启容器
docker stop (容器id or 容器名)    # 停止容器
docker kill (容器id or 容器名)    # 强制停止容器

删除容器

docker rm 容器id                 # 删除指定容器 
docker rm -f $(docker ps -a -q) # 删除所有容器 
docker ps -a -q|xargs docker rm # 删除所有容器

删除和停止容器的区别在于,停止了容器,后续可以通过docker ps -a 查询全部容器,然后重启已经停止的容器,然而docker rm的话,就无法重启了,因为此容器不存在了。

进入正在运行的容器

# 命令1
docker exec -it 容器id bashShell
# 命令2
docker attach 容器id

查看容器/镜像的元数据

# 命令
docker inspect 容器id

docker inspect 39f20f911169                                                    
[
    {
        "Id": "39f20f911169249f652bd1686e8833bbece65d9a2e3f949d2c30e6aa487ea4a8",
        "Created": "2021-09-04T11:56:13.8819721Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 4217,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-09-04T12:11:44.1859855Z",
            "FinishedAt": "2021-09-04T12:11:40.6349685Z"
        },
        ...

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

# 命令
docker cp 容器id:容器内路径 目的主机路径

docker attach 39f20f911169                                                     1 ↵ 
[root@39f20f911169 /]# ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@39f20f911169 /]# cd home
[root@39f20f911169 home]# ls
[root@39f20f911169 home]# touch text.c
[root@39f20f911169 home]# ls
text.c
~ » docker attach 39f20f911169                                                     
[root@39f20f911169 home]# ls
text.c
[root@39f20f911169 home]# pwd
/home
[root@39f20f911169 home]# exit
exit

~ » docker cp 39f20f911169:/home/text.c ~                                              
~ » ls |grep text.c                                                                    
text.c

小结

attach  # 当前 shell 下attach 连接指定运行镜像
build  # 通过 Dockerfile 定制镜像
commit  # 提交当前容器为新的镜像
cp  #从容器中拷贝指定文件或者目录到宿主机中
create  # 创建一个新的容器,同run,但不启动容器
diff  # 查看 docker 容器变化
events  # 从 docker 服务获取容器实时事件
exec # 在已存在的容器上运行命
令
export  # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
history  # 展示一个镜像形成历史
images  # 列出系统当前镜像
import  # 从tar包中的内容创建一个新的文件系统映像[对应export]
info  # 显示系统相关信息
inspect  # 查看容器详细信息
kill  # kill 指定 docker 容器
load  # 从一个 tar 包中加载一个镜像[对应 save]
login  # 注册或者登陆一个docker 源服务器
logout  # 从当前 Dockerregistry 退出
logs  # 输出当前容器日志信息
port  #查看映射端口对应的容器内部源端口
pause  # 暂停容器
ps  # 列出容器列表
pull  #从docker镜像源服务器拉取指定镜像或者库镜像
push  #推送指定镜像或者库镜像至docker源服务器
restart  # 重启运行的容器
rm  # 移除一个或者多个容器
rmi  # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run  # 创建一个新的容器并运行一个命令
save  # 保存一个镜像为一个tar 包[对应 load]
search  # 在 docker hub 中搜索镜像
start  # 启动容器
stop  # 停止容器
tag  # 给源中镜像打标签
top  # 查看容器中运行的进程信息
unpause  # 取消暂停容器
version  # 查看 docker 版本号
wait  # 截取容器停止时的退出状态值

练习

使用docker安装nginx

#先搜索nginx
~ » docker search nginx                                                                
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15416     [OK]

# 拉取nginx镜像
~ » docker pull nginx                                                            125 ↵ 
Using default tag: latest
latest: Pulling from library/nginx
a330b6cecb98: Already exists
5ef80e6f29b5: Pull complete
f699b0db74e3: Pull complete
0f701a34c55e: Pull complete
3229dce7b89c: Pull complete
ddb78cb2d047: Pull complete
Digest: sha256:a05b0cdd4fc1be3b224ba9662ebdf98fe44c09c0c9215b45f84344c12867002e
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

#运行后台容器并且取别名nginx1,使用主机端口3344容器端口80
» docker run -d --name nginx1 -p 3344:80 nginx                                 125 ↵ 
4e5e2154d958e92ee873850c3d207309eac3bb6992367381c6ccedd5d7885f1b

# curl内网测试,打印结果测试成功
~ » curl localhost:3344                                                            3 ↵ 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }

安装tomcat

# 官方文档解释
# -it :交互模式
# --rm:容器启动成功并退出以后容器就自动移除,一般在测试情况下使用! docker run -it --rm tomcat:9.0
# 1、下载tomcat镜像 docker pull tomcat
# 2、启动
docker run -d -p 8080:8080 --name tomcat9 tomcat
# 3、进入tomcat
docker exec -it tomcat9 /bin/bash
# 4、思考:我们以后要部署项目,还需要进入容器中,是不是十分麻烦,要是有一种技术,可以将容器 内和我们Linux进行映射挂载就好了?我们后面会将数据卷技术来进行挂载操作,也是一个核心内容,这 里大家先听听名词就好,我们很快就会讲到!

安装es+kibana

# 我们启动es这种容器需要考虑几个问题
1、端口暴露问题 9200、9300
2、数据卷的挂载问题 data、plugins、conf 3、吃内存 - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
# 扩展命令
docker stats 容器id # 查看容器的cpu内存和网络状态

# 1、启动es测试
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 2、启动之后很卡,使用 docker stats 容器id 查看下cpu状态 ,发现占用的很大

# 3、增加上内存限制启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2

# 4、启动之后,使用 docker stats 查看下cpu状态, cpu占用变得很小

# 思考:如果我们要使用 kibana , 如果配置连接上我们的es呢?网络该如何配置呢?

Docker镜像原理

什么是镜像

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

镜像原理

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统, 它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 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等等。

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

镜像commit

docker commit 提交容器副本使之成为一个新的镜像!

# 语法
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名]

测试

# 1、从Docker Hub 下载tomcat镜像到本地并运行 -it 交互终端 -p 端口映射
~ » docker run -it  -p 8080:8080 tomcat
# docker启动官方tomcat镜像的容器,发现404是因为tomcat的webapps下没有root等文件!
~ » docker exec -it 1c2dbf45f698 /bin/bash

root@1c2dbf45f698:/usr/local/tomcat# cp webapps.dis/* webapps/

root@1c2dbf45f698:/usr/local/tomcat/webapps# exit

~ » docker ps -a                                                                       
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS                       PORTS      NAMES
1c2dbf45f698   tomcat    "catalina.sh run"   5 minutes ago   Exited (143) 2 minutes ago

# 2、当前运行的tomcat实例就是一个没有docs的容器,我们使用它为模板commit一个没有docs的comcat新镜像, tomcat1
~ » docker commit 1c2dbf45f698 tomcat1:1.0                                             
sha256:b1a4a602a5ec0a5bcec050c150100f3f9e5c49464b872c64b06a5e44205dbdea

~ » docker images                                                                      
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
tomcat1                     1.0       b1a4a602a5ec   8 seconds ago   684MB
tomcat                      latest    ab1f0e1bb1a1   23 hours ago    680MB

容器数据卷

概念

将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够持久化的!容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成 新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!

作用:
卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

特点:

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

使用方法

命令挂载
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名

~ »  docker run -it -v /home/ceshi:/home centos /bin/bash

查看数据卷是否挂载成功 docker inspect 容器id

<img src="../myhexo/source/images/image-20210906220905936.png" alt="image-20210906220905936" style="zoom:50%;" />

测试容器和宿主机之间数据共享:可以发现,在容器中,创建的会在宿主机中看到!

安装mysql

# 注意: mysql的数据应该不丢失!先体验下 -v 挂载卷! 参考官方文档
~ » docker run -d -p 3310: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 4763fa5c68c4323688102f57938fb10996a0fb902d2812349286529f9378f16c
# 4、使用本地的sqlyog连接测试一下 3310
# 5、查看本地的 /home/mysql 目录
~ » pwd /home/mysql/data 
~ » ls
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着
# 6、删除mysql容器
~ » docker rm -f mysql01 # 删除容器,然后发现远程连接失败! 
mysql01
~ »  ls
.. ... . test # 可以看到我们刚刚建立的mysql数据库在本地存储着

通过Docker File 来添加

写dockerfile脚本

FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"] CMD echo "-------end------"
CMD /bin/bash
#  编译脚本 -f:file -t:target 后面有个点
~/docker-test-volume » docker build -f /Users/pang/docker-test-volume/dockerfile1 -t pang/centos .
              [+] Building 0.2s (5/5) FINISHED
               => [internal] load build definition from dockerfile1                                     0.0s
               => => transferring dockerfile: 157B                                                      0.0s
               => [internal] load .dockerignore                                                         0.0s
               => => transferring context: 2B                                                           0.0s
               => [internal] load metadata for docker.io/library/centos:latest                          0.0s
               => [1/1] FROM docker.io/library/centos                                                   0.0s
               => exporting to image                                                                    0.0s
               => => exporting layers                                                                   0.0s
               => => writing image sha256:928e07edc321556cd0c4aaa7ccf53b8952599a52bba1c06cfaab8907c9d7  0.0s
               => => naming to docker.io/pang/centos                                                    0.0s
               
# 查看镜像,发现生成了我们自己的镜像pang/centos
~/docker-test-volume » docker images                                              
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
mysql                    latest    0716d6ebcc1a   3 days ago     514MB
pang/centos              latest    928e07edc321   9 months ago   209MB
centos                   latest    300e315adb2f   9 months ago   209MB
justincormack/nsenter1   latest    c81481184b1b   3 years ago    101kB

#后台运行这个容器
~/docker-test-volume » docker run -d 928e07edc321
# 进入容器在此容器里写个测试文件2
[root@a2158f98ccbf dataVolumeContainer2]# mkdir test2

# 查看容器详情
#发现dataVolumeContainer1和2 这两个卷已经跟系统默认的地址绑定
~ » docker inspect a2158f98ccbf                                                      
[
    { 
    ...
    "Mounts": [
            {
                "Type": "volume",
                "Name": "54c34557ba83af6f142a0916c7eddc36acdb1652eb9b5123ff5c40f6e1e7e4e8",
                "Source": "/var/lib/docker/volumes/54c34557ba83af6f142a0916c7eddc36acdb1652eb9b5123ff5c40f6e1e7e4e8/_data",
                "Destination": "/dataVolumeContainer2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "b2d98f27082a7864f83aaf667858f3fad39a02819cd4e00e61279a7d30589159",
                "Source": "/var/lib/docker/volumes/b2d98f27082a7864f83aaf667858f3fad39a02819cd4e00e61279a7d30589159/_data",
                "Destination": "/dataVolumecontainer1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        ...]
# 进入/var/lib/docker/volumes/b2d98f27082a7864f83aaf667858f3fad39a02819cd4e00e61279a7d30589159/_data
#发现我们在容器内创建的测试文件,的确同步到此数据卷中!!!!
/var/lib/docker/volumes/54c34557ba83af6f142a0916c7eddc36acdb1652eb9b5123ff5c40f6e1e7e4e8/_data # ls
test2

换句话说,通过脚本可以在镜像创建的同时指定数据卷,而此数据卷会对应系统默认的位置/var/lib/docker/volumes/xxxxxx

匿名和具名挂载

# 匿名挂载
#-v 容器内路径
#-P 随机端口
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护 
docker volume ls
# 具名挂载
-v 卷名:/容器内路径
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx
# 查看挂载的路径
~ » docker volume inspect nginxconfig 
[
    {
        "CreatedAt": "2020-05-13T17:23:00+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
} ]
# 怎么判断挂载的是卷名而不是本机目录名? 
# name不是/开始就是卷名,是/开始就是目录名

# 改变文件的读写权限
# ro: readonly
# rw: readwrite
# 指定容器对我们挂载出来的内容的读写权限
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。用于两个容器数据共享。

docker run -it --name docker02 -- volumes-from docker01 镜像名

测试:

# 开启docker1
~ » docker run -it --name docker1 pang/centos
#查看docker1目录
[root@e5ef3e8f59bb /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Sep  7 04:01 dataVolumeContainer2
drwxr-xr-x   2 root root 4096 Sep  7 04:01 dataVolumecontainer1
drwxr-xr-x   5 root root  360 Sep  7 04:01 dev
#开启docker2并且挂载到父容器docker1
~ » docker run -it --name docker2 --volumes-from docker1 pang/centos
#查看docker2目录,发现同步docker1的数据卷 dataVolumeContainer2,dataVolumecontainer1
[root@1f0476c5fa67 /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Sep  7 04:01 dataVolumeContainer2
drwxr-xr-x   2 root root 4096 Sep  7 04:01 dataVolumecontainer1
drwxr-xr-x   5 root root  360 Sep  7 04:02 dev

得出结论:
容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。存储在本机的文件则会一直保留!

DockerFile

dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 构建步骤:

  1. 编写DockerFile文件
  2. docker build 构建镜像
  3. docker run

DockerFile构建过程

基础知识:

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. "#" 表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

流程

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 执行类似 docker commit 的操作提交一个新的镜像层
  4. Docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成!

说明:

从应用软件的角度来看,DockerFile,docker镜像与docker容器分别代表软件的三个不同阶段。

  • DockerFile 是软件的原材料 (代码)
  • Docker 镜像则是软件的交付品 (.apk)
  • Docker 容器则是软件的运行状态 (客户下载安装执行)

DockerFile指令

FROM            # 基础镜像,当前新镜像是基于哪个镜像的 MAINTAINER # 镜像维护者的姓名混合邮箱地址
RUN             # 容器构建时需要运行的命令
EXPOSE          # 当前容器对外保留出的端口
WORKDIR         # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ENV             # 用来在构建镜像过程中设置环境变量
ADD             # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包 COPY # 类似ADD,拷贝文件和目录到镜像中!
VOLUME          # 容器数据卷,用于数据保存和持久化工作
CMD             # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最 后一个生效!
ENTRYPOINT      # 指定一个容器启动时要运行的命令!和CMD一样
ONBUILD         # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发

自定义个centos

官方自带的centos没有vim,ifconfig等命令,自己写一个centos镜像,封装这些功能。

  1. 编写DockerFlie

    ~/dockerfile-test » vim dockerfile_centos
    
                FROM centos
                MAINTAINER pang<xxxxx@gmail.com>
    
                ENV MYPATH /usr/local
                WORKDIR $MYPATH
    
                RUN yum -y install vim #-y参数是询问直接yes
                RUN yum -y install net-tools
    
                EXPOSE 80
    
                CMD echo $MYPATH
                CMD /bin/bash 
                #Dockerfile 中可以有多个CMD 指令,但只有最后一个生效 所以echo ¥MYPATH 不会生效
    
  2. 构建
    docker build -f dockerfile地址 -t 新镜像名字:TAG .

    最后一个点千万别忘记,那个点表示当前目录

    ~/dockerfile-test » docker build -f dockerfile_centos -t mycentos .                   
                [+] Building 25.4s (8/8) FINISHED
                 => [internal] load build definition from dockerfile_centos                                    0.0s
                 => => transferring dockerfile: 259B                                                           0.0s
                 => [internal] load .dockerignore                                                              0.0s
                 => => transferring context: 2B                                                                0.0s
                 => [internal] load metadata for docker.io/library/centos:latest                               0.0s
                 => CACHED [1/4] FROM docker.io/library/centos                                                 0.0s
                 => [2/4] WORKDIR /usr/local                                                                   0.0s
                 => [3/4] RUN yum -y install vim                                                              21.9s
                 => [4/4] RUN yum -y install net-tools                                                         2.7s
                 => exporting to image                                                                         0.6s
                 => => exporting layers                                                                        0.6s
                 => => writing image sha256:8285bc191d1840ab5fb5ab23377779d473dbf06acaf07810ca9b3d1e73852de9   0.0s
                 => => naming to docker.io/library/mycentos                                                    0.0s
    
                Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
    ----------------------------------------------------------------------------------------------------
    ~/dockerfile-test » docker images                                                      
    REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
    mycentos                 latest    8285bc191d18   31 seconds ago   292MB
    
  3. 运行
    docker run -it 新镜像名字:TAG

~/dockerfile-test » docker run -it mycentos     
#发现可以执行ifconfig
[root@a5025cb21d5d local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 7  bytes 586 (586.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 # 可以执行vim
[root@a5025cb21d5d local]# vim testvim
# 起始目录为/usr/local说明WORKDIR $MYPATH生效
[root@a5025cb21d5d local]# pwd
/usr/local

CMD 和 ENTRYPOINT 的区别

CMD:Dockerfile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换!

# dockerfile
FROM centos
CMD [ "ls", "-a" ]
# 执行
~/dockerfile-test »  docker run 554bc6952657 
.dockerenv
bin
dev
...
# 如果我们希望用 -l 列表展示信息,我们就需要加上 -l参数
~/dockerfile-test » docker run cmdtest -l
# 报错
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.

ENTRYPOINT:docker run 之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合!

FROM centos
ENTRYPOINT [ "ls", "-a" ]
# 执行
~/dockerfile-test » docker run ae07199f9144 
.dockerenv
bin
dev
etc
# 测试-l参数,发现可以直接使用,这里就是一种追加,我们可以明显的知道 CMD 和 ENTRYPOINT 的区别了
~/dockerfile-test » docker run entrypointtest -l
total 56
drwxr-xr-x   1 root root 4096 May 12 04:21 .
drwxr-xr-x   1 root root 4096 May 12 04:21 ..
...

自定义tomcat

  1. mkdir -p pang/build/tomcat
  2. 在上述目录下 touch readme.txt
  3. 将 JDK 和 tomcat 安装的压缩包拷贝进上一步目录
  4. 在 pang/build/tomcat 目录下新建一个Dockerfile文件
# vim Dockerfile
FROM centos
MAINTAINER pang<xxxx@gmial.com> 
#把宿主机当前上下文的read.txt拷贝到容器/usr/local/路径下
COPY read.txt /usr/local/cincontainer.txt
#把java与tomcat添加到容器中
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr/local/
#安装vim编辑器
RUN yum -y install vim
#设置工作访问时候的WORKDIR路径,登录落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java与tomcat环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin 
#容器运行时监听的端口
EXPOSE 8080
#启动时运行tomcat
# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.22/bin/startup.sh" ]
# CMD ["/usr/local/apache-tomcat-9.0.22/bin/catalina.sh","run"] 
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/bin/logs/catalina.out
  1. docker build -t diytomcat .
    dockerfile的文件名为dockerfile的时候 参数-f dockerfile可以省略

  2. 运行run,一切-v挂载文件,这样我们只需要修改宿主机上的文件,自动同步到容器数据卷中,就不需要进入容器了

    docker run -d -p 9090:8080 --name mydiytomcat -v
    /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-
    9.0.22/webapps/test -v
    /home/kuangshen/build/tomcat/tomcat9logs/:/usr/local/apache-tomcat-
    9.0.22/logs --privileged=true diytomcat
    
  3. 注意必须把html或者jsp放在tomcat的webapp文件夹下才可以访问到哦!

发布镜像

发布到Dockerhub

~/dockerfile-test » docker login -u pzym321                                            
Password:
Login Succeeded

~/dockerfile-test » docker push pzym321/mycentos:1.0                                  
The push refers to repository [docker.io/pzym321/mycentos]
0db5ea52e18d: Pushed
3914059f50a0: Pushed
5f70bf18a086: Pushed
...

注意:
首先必须带有版本号,其次斜杠前面的内容必须是自己的dockerhub用户名,否则会保denied: requested access to the resource is denied的错误

发布到阿里云服务器

  1. 登录阿里云
  2. 找到容器镜像服务
  3. 创建命名空间
  4. 创建镜像仓库
  5. 点击进入这个镜像仓库,可以看到所有的信息

详细的步骤请参考阿里云镜像服务!

总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容