0%

Docker使用

一次构建,处处运行!

为什么需要Docker

一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发和运维之间的协作,我们需要考虑更多的问题。特别是各种版本迭代后,不同版本环境的兼容等等都是我们所需要考虑的。

Docker之所以发展如此迅速,是因为它对以上的问题给出了一个标准化的解决方案。

形象的说:项目带着环境一起走!

Docker安装

前提说明

  • CentOs 7(64-bit)系统内核版本为3.10以上 uname -r 命令用于打印当前系统的相关内核
  • CentOs 6.5或更高版本上,要求系统为64位,系统内核版本为2.6.32-431或更高版本

Docker 的基本组成

  • 镜像(image)
  • 容器(container)# 可以把容器看做成一个简易版的Linux环境
  • 仓库(repository)
  • Docker架构图(重要)

安装步骤

CentOS Docker 安装

镜像加速

  • 阿里云镜像加速

进入阿里云官网,登录后进入容器镜像服务—>选择镜像工具—>镜像加速器—>根据对应系统进行配置操作

重启后终端输入docker info验证是否配置成功。

命令docker run hello-world 验证是否安装成功!

运行底层原理

Docker是怎么工作的

Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接,从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。

为什么docker比vm快

  • Docker有着比虚拟机更少的抽象层。由于Docker不需要Hypervisor实现硬件资源的虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。因此,在CPU、内存利用率上Docker将会在效率上有明显的优势。

  • Docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核,从而可以避免寻找、加载操作系统内核这个费时费资源的过程。当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返回新建过程是分钟级别的,而Docker由于直接利用宿主机的操作系统,则省略了返回过程,。因此,新建一个Docker容器只需要几秒

  • 对比!(重要)

Docker 常用命令

帮助命令

  • docker –help
  • docker info #查看docker的系统信息,包括镜像和容器的数量
  • docker 命令 –help #帮助命令(可查看可选的参数)

命令的帮助文档

镜像命令

  • docker images:列出本地主机上的镜像

REPOSITORY:镜像的仓库源;TAG:镜像的标签;IMAGE ID:镜像ID;CREATED:镜像创建的时间;VIRTUAL SIZE:镜像大小

** 我们使用Repository:Tag来表示一个镜像**

  • docker search 某个镜像的名称:搜索镜像 # docker search mysql
  • docker pull 某个镜像的名称[:TAG]:下载镜像 # eg :docker pull mysql:5.7 如果不写tag默认就是latest
  • docker rmi 某个镜像名称的ID:删除镜像
    1. 删除单个:docker rmi -f 镜像ID
    2. 删除多个:docker rmi -f 镜像名1:TAG 镜像名2:TAG
    3. 删除全部:docker rmi -f $(docker images -qa)

容器命令

  • docker run [options] image [command][arg…]:新建并启动交互式容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    options说明(常用):

    ​ -–name=”容器的新名字”:为容器指定一个名称;

    ​ -d:后台运行容器,并返回容器ID,也即启动守护式容器

    ​ -i:以交互模式运行容器,通常与-t同时使用

    ​ -t:为容器重新分配一个伪输入终端,通常与-i同时使用

    ​ -P:随机端口映射 (大写)

    ​ -p:指定端口映射,有以下4种形式:

    ​ ip:hostPort:containerPort

    ​ ip::containerPort

    ​ hostPort:containerPort

    ​ containerPort

    eg:运行并进入容器centos
    [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it centos /bin/bash

    [root@bd1b8900c547 /]# ls
    bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
    • 退出容器命令

      1
      2
      3
      4
      5
      6
      #exit 停止并退出容器(后台方式运行则仅退出)
      #Ctrl+P+Q 不停止容器退出
      [root@bd1b8900c547 /]# exit
      exit

      [root@iZwz99sm8v95sckz8bd2c4Z ~]#
    • 列出运行过的容器命令

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      docker ps [options]:列出当前所有正在运行的容器
      options说明(常用):

      ​ -a:列出当前所有正在运行的容器+历史上运行过的

      ​ -l:显示最近创建的容器

      ​ -n:显示最近n个创建的容器

      ​ -q:静默模式,只显示容器编号



      [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

      [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps -a
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      bca129320bb5 centos "/bin/bash" 4 minutes ago Exited (0) 3 minutes ago optimistic_shtern
      bd1b8900c547 centos "/bin/bash" 6 minutes ago Exited (0) 5 minutes ago cool_tesla
      cf6adbf1b506 bf756fb1ae65 "/hello" 5 hours ago Exited (0) 5 hours ago optimistic_darwin
    • 删除容器命令

      1
      2
      3
      docker rm 容器id                 #删除指定的容器,不能删除正在运行的容器,强制删除使用 rm -f
      docker rm -f $(docker ps -aq) #删除所有的容器
      docker ps -a -q|xargs docker rm #删除所有的容器
    • 启动和停止容器命令

      1
      2
      3
      4
      docker start 容器ID或者容器名          #启动容器
      docker restart 容器ID或者容器名 #重启容器
      docker stop 容器ID或者容器名 #停止当前运行的容器
      docker kill 容器ID或者容器名 #强制停止当前容器
    • 日志的查看

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      1.docker logs -f -t --tail 容器ID:查看容器日志
      -t:加入时间戳

      ​ -f:跟随最新的日志打印

      ​ –tail 数字:显示最后多少条

      2.docker top 容器ID:查看容器内运行的进程

      3.docker inspect 容器ID:查看容器内部细节

      4.进入正在运行的容器并以命令行交互
      docker exec -it 容器ID /bin/bash
      docker attach 容器ID
      区别:attach:直接进入容器启动命令的终端,不会启动新的进程;

      exec:在容器中打开新的终端,并且可以启动新的进程
    • 拷贝操作

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      #拷贝容器的文件到主机中
      docker cp 容器id:容器内路径 目的主机路径

      #拷贝宿主机的文件到容器中
      docker cp 目的主机路径 容器id:容器内路径

      [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it c703b5b1911f /bin/bash

      [root@c703b5b1911f /]# cd home

      [root@c703b5b1911f home]# ls

      #touch 新建文件
      [root@c703b5b1911f home]# touch test.java

      [root@c703b5b1911f home]# ls
      test.java

      [root@c703b5b1911f home]# exit
      exit

      [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
      c703b5b1911f centos "/bin/sh -c 'while t…" 35 minutes ago Up 35 minutes pedantic_banach

      [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker cp c703b5b1911f:/home/test.java /home

      [root@iZwz99sm8v95sckz8bd2c4Z ~]# ls /home
      hai pan test.java

常用容器部署

Nginx部署

  1. 搜索并下载镜像 docker search nginx

    dockerhub官网

  2. 运行测试

    1
    2
    3
    4
    5
    docker run -d --name nginx01 -p 3334:80 nginx 

    -d 后台运行
    --name 给容器命名
    -p 3334:80 将宿主机的端口3334映射到该容器的80端口
  3. 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker exec -it nginx01 /bin/bash

    root@20c896637ff5:/# whereis nginx
    nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx

    root@20c896637ff5:/# cd /etc/nginx

    root@20c896637ff5:/etc/nginx# ls
    conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf

    root@20c896637ff5:/# cd /etc/nginx

    root@20c896637ff5:/etc/nginx# ls
    conf.d fastcgi_params koi-utf koi-win mime.types modules nginx.conf scgi_params uwsgi_params win-utf
  4. 访问测试

1
2
3
4
5
6
7
本地主机访问测试,curl命令发起请求,如果使用阿里云服务器需要设置安全组。

[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20c896637ff5 nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 0.0.0.0:3334->80/tcp nginx01

[root@iZwz99sm8v95sckz8bd2c4Z ~]# curl localhost:3334
  1. 设置数据卷

启动Nginx容器的同时设置数据卷的命令

1
2
3
4
5
6
7
docker run --name my_nginx -d -p 80:80  -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf 
-v /data/nginx/log:/var/log/nginx -v /data/nginx/html:/usr/share/nginx/html nginx

参数说明:
第一个-v:挂载nginx的主配置文件,以方便在宿主机上直接修改容器的配置文件
第二个-v:挂载容器内nginx的日志,容器运行起来之后,可以直接在宿主机的这个目录中查看nginx日志
第三个-v:挂载静态页面目录

Tomcat部署

  1. docker pull tomcat
  2. docker run -d -p 3335:8080 –name tomcat01 tomcat
  3. docker exec -it tomcat01 /bin/bash # 下载的是最小的镜像,保证最小的运行环境
  4. cp -r /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps/ #这样才有“猫”
  5. exit
  6. curl localhost:3335

Redis部署

  1. docker hub上查找redis镜像:docker search redis:3.2

  2. 从docker hub上拉取redis镜像到本地,标签为3.2:docker pull redis:3.2

  3. 使用redis镜像 docker run -d -p 6379:6379 -v /myredis/conf:/usr/local/etc/redis –name myredis redis redis-server /usr/local/etc/redis/redis.conf –appendonly yes

  4. 在主机/home/myredis/conf/redis.conf 目录下新建redis.conf文件:vim /home/myredis/conf/redis.conf/redis.conf

  5. docker exec -it 运行着的Redis服务容器的ID redis-cli

  6. 退回宿主机,查看持久化文件appendonly.aof是否生成

MySQL部署

  1. docker run -d –name mysql-5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

    -p 3306:3306 :映射容器服务的 3306 端口到宿主机的 3306 端口,外部主机可以直接通过 宿主机ip:3306 访问到 MySQL 的服务。 MYSQL_ROOT_PASSWORD=123456:设置 MySQL 服务 默认账号root 用户的密码。

  2. docker exec -it 9b3aad6819ff /bin/bash

  3. mysql -h localhost -u root -p

Docker容器数据卷

是什么

Docker的理念

  • 将应用与运行时环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的
  • 容器之间希望有可能共享数据

Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据成为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。

为了能够保存数据,我们在Docker中使用卷

能干什么

  • 容器的持久化
  • 容器间继承+共享数据

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

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

特点:

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

添加数据卷

  1. 直接命令添加

    • 添加:docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
    • 查看数据卷是否挂载成功:docker inspect 容器ID 查看 Volumes
    • 容器和宿主机之间数据共享
    • 容器停止退出后,主机修改后数据是否同步:是
    • 命令(带权限):docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
  2. DockerFile添加

    • 根目录下新建mydocker文件夹并进入

    • 可在DockerFile中使用VOLUME指令来给镜像添加一个或多个数据卷 eg:VOLUME[“/dataVolumeContainer”,”/dataVolumeContainer2”,”/dataVolumeContainer3”] ps:出于可移植和分享的考虑,用-v /宿主机绝对路径目录:/容器内目录不能够直接在DockerFile中实现

    • File构建:例如

      1
      2
      3
      4
      FROM centos
      VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
      CMD echo "finished,----------success"
      CMD /bin/bash```
    • build后生成镜像 docker build -f /home/docker-test-volume/dockerfile01 -t ethan/centos:1.0 .

    • run容器 docker run -it 1df90e6fd790 /bin/bash

    • 对应主机目录地址:会有一个默认的地址 docker inspect 828d43dba78e

MySQL容器建立数据卷同步数据

1
2
3
docker run -d -p 6603: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

#在Linux下的MySQL默认的数据文档存储目录为/var/lib/mysql,默认的配置文件的位置/etc/mysql/conf.d,为了确保MySQL镜像或容器删除后,造成的数据丢失

具名挂载和匿名挂载

匿名挂载

匿名挂载就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。如下运行并匿名挂载Nginx容器

1
2
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
d3a27b969d122d5516cac75e99b17dff7aaaf1e0c042385c6b05990053f1259

查看所有的数据卷volume的情况, VOLUME NAME这里的值是真实存在的目录

1
2
3
4
5
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker volume ls
DRIVER VOLUME NAME
local 0cd45ab893fc13971219ac5127f9c0b02491635d76d94183b0261953bdb52d26
local 668a94251e562612880a2fdb03944d67d1acdbbdae6ef7c94bee8685644f2956
local e605f3dc4bf11ab693972592b55fb6911e5bf2083425fd58869c5f574998a09a

具名挂载

具名挂载,就是指定文件夹名称,区别于指定路径挂载,这里的指定文件夹名称是在Docker指定的默认数据卷路径下的。通过docker volume ls命令可以查看当前数据卷的目录情况。

1
2
3
4
5
6
7
8
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
4ceaff19e5275dcd3014a8e7a8af618f7f7ce0da18d605c7c41a8653e78bf912
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker volume ls
DRIVER VOLUME NAME
local 0cd45ab893fc13971219ac5127f9c0b02491635d76d94183b0261953bdb52d26
local 668a94251e562612880a2fdb03944d67d1acdbbdae6ef7c94bee8685644f2956
local e605f3dc4bf11ab693972592b55fb6911e5bf2083425fd58869c5f574998a09a
local juming-nginx

查看指定的数据卷信息的命令:docker volume inspect数据卷名称

1
2
3
4
5
6
7
8
9
10
11
12
[root@iZwz99sm8v95sckz8bd2c4Z ~]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-12-29T22:40:25+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]

可以看到主机数据卷挂载在/var/lib/docker/volumes/juming-nginx/_data上

Docker所有的数据卷默认在/var/lib/docker/volumes/ 目录下

匿名挂载,具名挂载,指定路径挂载的命令区别如下:
-v 容器内路径 #匿名挂载

-v 卷名:容器内路径 #具名挂载

-v /宿主机路径:容器内路径 #指定路径挂载

指定数据卷映射的相关参数:

ro —— readonly 只读。设置了只读则只能操作宿主机的路径,不能操作容器中的对应路径。

rw —– readwrite 可读可写

容器数据卷

容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。

  • 首先启动容器1,volume01、volume02为挂载目录

    1
    2
    3
    [root@iZwz99sm8v95sckz8bd2c4Z ~]# docker run -it --name cnetos01 ethan/centos:1.0
    [root@731d53b8c3d5 /]# ls
    bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
  • 然后启动容器2,通过参数--volumes-from,设置容器2和容器1建立数据卷挂载关系

    1
    2
    [root@iZwz99sm8v95sckz8bd2c4Z /]# docker run -it --name centos02 --volumes-from cnetos01 ethan/centos:1.0
    [root@7f90d4147511 /]# ls -l
  • 首先在容器2中的volume01中添加文件

    1
    2
    3
    4
    [root@7f90d4147511 /]# cd volume01
    [root@7f90d4147511 volume01]# touch test.java
    [root@7f90d4147511 volume01]# ls
    test.java
  • 然后就可以看到容器1的文件也会添加上了

结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有任何容器使用它为止

DockerFile解析

是什么

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

构建三步骤:(1)编写DockerFile文件(2)docker build(3)docker run

DockerFile构建过程解析

  1. DockerFile内容基础知识
    • 每条保留字指令都必须为大写字母,且后面要跟随至少一个参数
    • 指令按照从上到下,顺序执行
    • #表示注释
    • 每条指令都会创建一个新的镜像层,并对镜像进行提交
    • Dockerfile指令介绍的官方
  2. Docker执行DockerFile的大致流程
    • docker从基础镜像运行一个容器
    • 执行一条指令并对容器作出修改
    • 执行类似docker commit的操作提交一个新的镜像层
    • docker再基于刚提交的镜像运行一个新容器
    • 执行DockerFile中的下一条执行,直到所有指令都执行完成

总结

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

  • DockerFile是软件的原材料
  • Docker镜像是软件的交付品
  • Docker容器则可以认为是软件的运行态

DockerFile 保留字

  • FROM:基础镜像,当前镜像是基于哪个镜像的

  • MAINTAINER:镜像维护者的姓名和邮箱地址

  • RUN:容器构建时需要运行的命令

  • EXPOSE:当前容器对外暴露出的端口号

  • WORKDIR:指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点

  • ENV:用来构建镜像过程中设置环境变量

  • ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

  • COPY:类似ADD,拷贝文件和目录到镜像中

  • VOLUME:容器数据卷,用于数据保存和持久化工作

  • CMD:指定一个容器启动时要运行的命令。DockerFile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

  • ENTRYPOINT:指定一个容器启动时要运行的命令。指定容器启动程序和参数。docker run之后的参数会传递给ENTRYPOINT,之后形成新的命令组合

  • ONBUILD:当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的onbuild被触发

制作Centos镜像

下面通过编写Dockerfile文件来制作Centos镜像,并在官方镜像的基础上添加vim和net-tools工具。首先在/home/dockfile 目录下新建文件mydockerfile-centos。然后使用上述指令编写该文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat mydockerfile-centos
FROM centos:7
MAINTAINER ethan<1258398543@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

逐行解释该Dockerfile文件的指令:

  • FROM centos:该image文件继承官方的centos,后面加冒号如centos:7,用于指定镜像的版本
  • ENV MYPATH /usr/local:设置环境变量MYPATH ,后面有用到
  • WORKDIR $MYPATH:直接使用上面设置的环境变量,指定/usr/local为工作目录
  • RUN yum -y install vim和RUN yum -y install net-tools:在/usr/local目录下,运行yum -y install vim和yum -y install net-tools命令安装工具,注意安装后的所有依赖和工具都会打包到image文件中
  • EXPOSE 80:将容器80端口暴露出来,允许外部连接这个端口
  • CMD:指定容器启动的时候运行命令

通过这个dockerfile构建镜像,构建镜像命令:docker build -f dockerfile文件路径 -t 镜像名[:版本号] .(这里有个小点.)

上面命令中,-t参数用来指定 image 文件的名字,后面还可以用冒号指定标签。如果不指定,默认的标签就是latest。最后的那个点表示 Dockerfile 文件所在的路径,上例是当前路径,所以是一个点。

如果执行成功,可以通过docker images来查看新生成的镜像文件

下面生成容器,测试相关命令,查看默认工作目录是否设置成功,vim和net-tools工具是否下载成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run -it mycentos:1.0

[root@e548efe82b30 local]# pwd
/usr/local

#net-tools工具提供ifconfig命令
[root@e548efe82b30 local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
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

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

[root@e548efe82b30 local]# vi test.txt

[root@e548efe82b30 local]# cat test.txt
Hello world!

另外,我们通过docker history 容器id命令来查看镜像的构建步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker history 1185a46e3a12
IMAGE CREATED CREATED BY SIZE COMMENT
1185a46e3a12 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
83459c404586 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
9b8661c812c4 13 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
2064c1540e8e 13 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
1b15d4a1fd5e 13 minutes ago /bin/sh -c yum -y install net-tools 23.3MB
9336c20f0b6d 13 minutes ago /bin/sh -c yum -y install vim 58MB
7d46880ef0fd 14 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
e27a56b5247b 14 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
b2b6851e55fa 14 minutes ago /bin/sh -c #(nop) MAINTAINER ethan<12583985… 0B
300e315adb2f 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB

RUN,CMD和ENTRYPOINT的区别

RUN命令与CMD命令的区别在哪里?

简单说,RUN命令在 image 文件的构建阶段执行,执行结果都会打包进入 image 文件;CMD命令则是在容器启动后执行。另外,一个 Dockerfile 可以包含多个RUN命令,但是只能有一个CMD命令。

注意,指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否则它会覆盖CMD命令。

CMD和ENTRYPOINT的区别在哪里?

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

下面来验证:

首先是使用CMD指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]

[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:1.0 .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
---> Running in 6d4d0112322f
Removing intermediate container 6d4d0112322f
---> b6ec5224d2ac
Successfully built b6ec5224d2ac
Successfully tagged cmdtest:1.0

[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:1.0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

#由于使用的是 CMD指令,命令无追加,-l取代了原本的ls -a,而-l命令不存在所以报错。
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:1.0 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

可以看到追加命令-l 出现了报错。

下面使用ENTRYPOINT来构建一个镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#1.修改dockerfile文件
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# cat dockerfile-cmd-test
FROM centos
ENTRYPOINT ["ls","-a"]
#2.构建镜像

[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest:2.0 .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 61389c0c1967
Removing intermediate container 61389c0c1967
---> ac7b7e83ff88
Successfully built ac7b7e83ff88
Successfully tagged cmdtest:2.0

#3.运行镜像
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:2.0
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

#4.追加镜像再次运行
[root@iZwz99sm8v95sckz8bd2c4Z dockerfile]# docker run cmdtest:2.0 -l
total 56
drwxr-xr-x 1 root root 4096 Jan 1 03:55 .
drwxr-xr-x 1 root root 4096 Jan 1 03:55 ..
-rwxr-xr-x 1 root root 0 Jan 1 03:55 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 340 Jan 1 03:55 dev
drwxr-xr-x 1 root root 4096 Jan 1 03:55 etc
drwxr-xr-x 2 root root 4096 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 15:22 media
drwxr-xr-x 2 root root 4096 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 4096 Nov 3 15:22 opt
dr-xr-xr-x 106 root root 0 Jan 1 03:55 proc
dr-xr-x--- 2 root root 4096 Dec 4 17:37 root
drwxr-xr-x 11 root root 4096 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Dec 29 15:41 sys
drwxrwxrwt 7 root root 4096 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec 4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec 4 17:37 var

没有报错!

制作Tomcat镜像并发布镜像

  1. 准备镜像文件tomcat、jdk压缩包

    1
    2
    3
    4
    5
    6
    7
    [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# vi readme.txt

    [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# ll
    total 200700
    -rw-r--r-- 1 root root 10371538 Jan 1 16:11 apache-tomcat-8.5.55.tar.gz
    -rw-r--r-- 1 root root 195132576 Jan 1 16:13 jdk-8u251-linux-x64.tar.gz
    -rw-r--r-- 1 root root 20 Jan 1 16:14 readme.txt
  2. 编写dockerfile文件,文件名使用官方命名:Dockerfile ,build的时候会默认寻找当前目录下的文件,不需要使用-f参数指定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# vim Dockerfile

    [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# cat Dockerfile
    FROM centos
    MAINTAINER ethan<1258398543@qq.com>

    COPY readme.txt /usr/local/readme.txt

    ADD jdk-8u251-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-8.5.55.tar.gz /usr/local/

    RUN yum -y install vim

    ENV MYPATH /usr/local
    WORKDIR $MYPATH

    ENV JAVA_HOME /usr/local/jdk1.8.0_251
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.55
    ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.55
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

    EXPOSE 8080

    CMD /usr/local/apache-tomcat-8.5.55/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.55/logs/catalina.out
  3. 使用该Dockerfile构建镜像 docker build -t diytomcat:1.0 .

  4. 构建Tomcat容器

    1
    [root@iZwz99sm8v95sckz8bd2c4Z tomcat]# docker run -d -p 8088:8080 --name diytomcat -v /home/dockerfile/tomcat/test:/usr/local/apache-tomcat-8.5.55/webapps/test -v /home/dockerfile/tomcat/logs:/usr/local/apache-tomcat-8.5.55/logs/ diytomcat:1.0
  5. 在/home/dockerfile/tomcat/test的目录下,新建index.html 测试Tomcat是否能正常使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #在index.html 写入以下内容!
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8"/>
    <title>这是个标题</title>
    </head>
    <body>
    <h1>这是一个一个简单的HTML</h1>
    <p>Hello World!</p>
    </body>
    </html>
  6. 访问测试,浏览器访问查看是否能正常访问

发布镜像到阿里云容器服务

  1. 登录阿里云,找到容器镜像服务
  2. 创建命名空间
  3. 按官方提供的操作指南操作即可