整理自尚硅谷周阳老师docker笔记
Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。
Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在 Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
Docker版本 docker-io 是以前早期的版本,版本号是 1.*,最新版是 1.13,而 docker-ce 是新的版本,分为社区版 docker-ce 和企业版 docker-ee,版本号是 17.*
一次构建、随处运行
Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。 Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。 比较 Docker 和传统虚拟化方式的不同之处:
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程。而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。docker官网:http://www.docker.com docker 中文网站:https://www.docker-cn.com/ Docker Hub官网(仓库,一般用阿里网易镜像加速):https://hub.docker.com/
CentOS Docker 安装 Docker支持以下的CentOS版本:
CentOS 7 (64-bit)CentOS 6.5 (64-bit) 或更高的版本前提条件
目前,CentOS 仅发行版本中的内核支持 Docker。
Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。查看自己的内核 uname 命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)。
[root@localhost ~]$ uname -r 2.6.32-642.el6.x86_64查看已安装的CentOS版本信息(CentOS6.8有,CentOS7无该命令)
[root@localhost ~]$ cat /etc/redhat-release CentOS release 6.8(Final)Centos6更新yum源仓库,升级内核
[root@localhost ~]$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo [root@localhost ~]$ yum clean all [root@localhost ~]$ yum -y update [root@localhost ~]$ yum makecache如果报错If above article doesn't help to resolve this issue please open a ticket wit
http://mirrors.cloud.aliyuncs.com/centos/6/os/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 6 - "Couldn't resolve host 'mirrors.cloud.aliyuncs.com'"
解决办法: CentOS 6已经经历了2020年11月的结束进入了EOL(生命终结),不过有一些老设备依然需要支持,CentOS官方也给这些还不想把CentOS 6扔进垃圾堆的用户保留了最后一个版本的充分,只是这个有意义不会再有更新了
官方便在12月2日正式将CentOS 6相关的软件源移出了官方资源,随之而来逐级甚至也会陆续将其删除。
一键修复(复制到SSH执行即可):
[root@localhost ~]$ sed -i "s|enabled=1|enabled=0|g" /etc/yum/pluginconf.d/fastestmirror.conf [root@localhost ~]$ mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup [root@localhost ~]$ curl -o /etc/yum.repos.d/CentOS-Base.repo https://www.xmpan.com/Centos-6-Vault-Aliyun.repo [root@localhost ~]$ yum clean all [root@localhost ~]$ yum makecacheELRepo 仓库是基于社区的用于企业级 Linux 仓库,提供对 RedHat Enterprise (RHEL) 和 其他基于 RHEL的 Linux 发行版(CentOS、Scientific、Fedora 等)的支持。
ELRepo 聚焦于和硬件相关的软件包,包括文件系统驱动、显卡驱动、网络驱动、声卡驱动和摄像头驱动等。#导入ELRepo仓库的公共密钥
[root@localhost ~]$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org安装ELRepo仓库的yum源
[root@localhost ~]$ rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm安装 kernel-lt(lt=long-term)lt长期稳定版
[root@localhost ~]$ yum --enablerepo=elrepo-kernel install kernel-lt -y编辑grub.conf文件,修改Grub引导顺序
[root@localhost ~]$ vim /etc/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a /boot partition. This means that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/mapper/vg_centos6-lv_root # initrd /initrd-[generic-]version.img #boot=/dev/sda default=1 #0,修改成4.4的内核,改成0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title CentOS (4.4.239-1.el6.elrepo.x86_64) root (hd0,0) kernel /vmlinuz-4.4.239-1.el6.elrepo.x86_64 ro root=/dev/mapper/vg_centos6-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_centos6/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_centos6/lv_root KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet initrd /initramfs-4.4.239-1.el6.elrepo.x86_64.img title CentOS 6 (2.6.32-642.el6.x86_64) root (hd0,0) kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=/dev/mapper/vg_centos6-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_centos6/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_centos6/lv_root KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet initrd /initramfs-2.6.32-642.el6.x86_64.img [root@localhost ~]$ reboot #重启系统Centos7更新yum源仓库,升级内核
[root@localhost ~]$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 或者 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo [root@localhost ~]$ yum clean all [root@localhost ~]$ yum -y update [root@localhost ~]$ yum makecacheELRepo 仓库是基于社区的用于企业级 Linux 仓库,提供对 RedHat Enterprise (RHEL) 和 其他基于 RHEL的 Linux 发行版(CentOS、Scientific、Fedora 等)的支持。
ELRepo 聚焦于和硬件相关的软件包,包括文件系统驱动、显卡驱动、网络驱动、声卡驱动和摄像头驱动等。#导入ELRepo仓库的公共密钥
[root@localhost ~]$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org安装ELRepo仓库的yum源
[root@localhost ~]$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm查看可用的系统内核包
[root@localhost ~]$ yum --disablerepo="*" --enablerepo="elrepo-kernel" list available安装最新版本内核
–enablerepo 选项开启 CentOS 系统上的指定仓库。默认开启的是 elrepo,这里用 elrepo-kernel 替换。
[root@localhost ~]$ yum --enablerepo=elrepo-kernel install kernel-ml查看系统上的所有可用内核
[root@localhost ~]$ awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg 0 : CentOS Linux (4.18.7-1.el7.elrepo.x86_64) 7 (Core) 1 : CentOS Linux (3.10.0-862.11.6.el7.x86_64) 7 (Core) 2 : CentOS Linux (3.10.0-514.el7.x86_64) 7 (Core) 3 : CentOS Linux (0-rescue-063ec330caa04d4baae54c6902c62e54) 7 (Core)设置 GRUB 默认的内核版本
编辑 /etc/default/grub 文件设置 GRUB_DEFAULT=0,通过上面查询显示的编号为 0 的内核作为默认内核:
[root@localhost ~]$ vim /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=0 GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=cl/root rhgb quiet" GRUB_DISABLE_RECOVERY="true"运行下面的命令来重新创建内核配置。
[root@localhost ~]$ grub2-mkconfig -o /boot/grub2/grub.cfg验证
[root@localhost ~]$ uname -r删除旧内核
[root@localhost ~]$ rpm -qa | grep kernel [root@localhost ~]$ yum remove kernel-3.10.0-514.el7.x86_64CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker不稳定
[root@localhost ~]$ rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm # 安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有,再安装一次! [root@localhost ~]$ yum --enablerepo=elrepo-kernel install -y kernel-lt # 设置开机从新内核启动 [root@localhost ~]$ grub2-set-default 'CentOS Linux (4.4.189-1.el7.elrepo.x86_64) 7 (Core)' && reboot镜像,简单的来说,就是面向对象中的类,相当于一个模板。Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。
Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。 容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的
仓库(Repository)是集中存放镜像文件的场所。
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为**公开仓库(Public)和私有仓库(Private)**两种形式。 最大的公开仓库是 Docker Hub(https://hub.docker.com/), 存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等
Docker架构图Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装相应的EPEL包。
[root@localhost ~]$ yum install -y epel-release [root@localhost ~]$ yum install -y docker-io安装后的配置文件:
[root@localhost ~]$ cat /etc/sysconfig/docker # etc/sysconfig/docker # # other arguments to pass to the docker daemon process # These wiil be parsed by the sysv initscript and appended # to the arguments list passed to docker -d other_args= DOCKER_CERT_PATH=ietc/docker # Resolves:rhbz#1176302( docker issue #407) DOCKER_NOWARN_KERNEL_VERSION=1 # Location used for temporary files,such as those created by # # docker load and build operations. Default is /var/lib/docker/tmp # # Can be overriden by setting the following environment variable. # # DOCKER_TMPDIR=/var/tmp启动Docker后台服务:
[root@localhost ~]$ service docker start验证是否安装成功:
[root@localhost ~]$ docker version卸载Docker
查询安装过的包:
[root@localhost ~]$ yum list installed | grep docker docker-io.x86_64 1.7.1-2.el6 @epel删除安装的软件包:
[root@localhost ~]$ yum -y remove docker-io.x86_64官网中文安装参考手册
安装gcc相关:
[root@localhost ~]$ yum -y install gcc [root@localhost ~]$ yum -y install gcc-c++卸载旧版本:
[root@localhost ~]$ yum -y remove docker docker-common docker-selinux docker-engine安装需要的软件包:
[root@localhost ~]$ yum install -y yum-utils device-mapper-persistent-data lvm2设置stable镜像仓库:
[root@localhost ~]$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo更新yum软件包索引:
[root@localhost ~]$ yum makecache fast安装Docker ce:
[root@localhost ~]$ yum -y install docker-ce启动docker:
[root@localhost ~]$ systemctl start docker测试:
[root@localhost ~]$ docker version配置镜像加速:
阿里云镜像加速
[root@localhost ~]$ mkdir -p /etc/docker [root@localhost ~]$ vim /etc/docker/daemon.json #网易云 {"registry-mirrors": ["http://hub-mirror.c.163.com"] } #阿里云 { "registry-mirrors": ["https://{自已的编码}.mirror.aliyuncs.com"] } [root@localhost ~]$ systemctl daemon-reload [root@localhost ~]$ systemctl restart docker卸载:
[root@localhost ~]$ systemctl stop docker [root@localhost ~]$ yum -y remove docker-ce [root@localhost ~]$ rm -rf /var/lib/docker启动Docker后台容器:
[root@localhost ~]$ docker pull hello-world [root@localhost ~]$ docker run hello-worldrun干了什么?
Docker是怎么工作的? 详细了解Docker怎么工作的 Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是鲸鱼背上的集装箱。 为什么Docker比较比VM快?
docker有着比虚拟机更少的抽象层。由亍docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
docker利用的是宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。仍而避免引寻、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。
有镜像才能创建容器,这是根本前提(下载一个CentOS镜像演示)
[root@localhost ~]$ docker pull centos启动交互式容器:
[root@localhost ~]$ docker run -it centos /bin/bash #使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。docker run 后面指定的是一个镜像 docker start 指定的是一个容器 docker run是利用镜像生成容器,并启动容器,而docker start是启动一个之前生成过的容器
docker run只有在第一次运行时使用,将镜像放到容器中,以后再次启动这个容器的时候,只需要使用命令docker start就可以。 docker run相当于执行了两步操作:将镜像(Image)放到容器(Container)中,这一步过程叫做docker create,然后将容器启动,使之变成运行时容器(docker start)。
docker start的作用是:重新启动已经存在的容器。也就是说,如果使用这个命令,我们必须先要知道这个容器的ID、或者这个容器的名字,我们可以使用docker ps命令找到这个容器的信息。
列出最近创建的5个容器信息:
[root@localhost ~]$ docker ps -n 5容器停止退出:
[root@localhost ~]$ exit容器不停止退出: ctrl+P+Q
重要
然后docker ps -a 进行查看, 会发现容器已经退出 很重要的要说明的一点:Docker容器后台运行,就必须有一个前台进程. 容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可
exec和attach的区别:
exec 是在容器中打开新的终端,并且可以启动新的进程,可以在容器外面直接运行命令,也可以进入容器里面运行命令
attach 直接进入容器启动命令的终端,不会启动新的进程
查看容器内的目录:
[root@localhost ~]$ docker exec -it 容器ID ls将主机/www/runoob目录拷贝到容器96f7f14e99ab的/www目录下:
[root@localhost ~]$ docker cp /www/runoob 96f7f14e99ab:/www/将容器96f7f14e99ab的/www目录拷贝到主机的/tmp目录中:
[root@localhost ~]$ docker cp 96f7f14e99ab:/www /tmp/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等等。
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
Docker镜像特点
Docker镜像都是只读的 当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
docker commit提交容器副本使之成为一个新的镜像
语法格式:
[root@localhost ~]$ docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]案例:
从Hub上下载tomcat镜像到本地并成功运行
[root@localhost ~]$ docker run -it -p 8080:8080 tomcat故意删除上一步镜像生产tomcat容器的文档
[root@localhost ~]$ docker ps [root@localhost ~]$ docker exec -it d5345dfs345(容器id) /bin/bash [root@d5345dfs345 ]$ ls -l [root@d5345dfs345 ]$ cd /usr/local/tomcat/webapps [root@d5345dfs345 ]$ rm -rf docs也即当前的tomcat运行实例是一个没有文档内容的容器,以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat02
[root@localhost ~]$ docker commit -a="root" -m="delete tocat docs" d5345dfs345 demo/tomcat02:1.2启动我们的新镜像并和原来的对比
[root@localhost ~]$ docker run -it -p 7777:8080 demo/tomcat02:1.2 [root@localhost ~]$ docker run -it -p 8888:8080 tomcat先来看看Docker的理念:
将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的容器之间希望有可能共享数据Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。
为了能保存数据在docker中我们使用卷。有点类似我们Redis里面的rdb和aof文件
容器的持久化 容器间的继承+共享数据
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷
特点:
数据卷可在容器之间共享或重用数据卷中的更改可以直接生效数据卷中的更改不会包含在镜像的更新中数据卷的生命周期一直持续到没有容器使用它为止容器内目录和宿主机目录进行挂载
命令:
[root@localhost ~]$ docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名案例: 在容器中创建 mydataVolume 目录,与宿主机的 /dataVolumeContainer绑定,实现数据共享
[root@localhost ~]$ docker run -it -v /mydataVolume:/dataVolumeContainer centos查看数据卷是否挂载成功:
[root@localhost ~]$ docker inspect 容器ID "Volumes": { "/dataVolumeContainer": "/mydataVolume" }; "VolumesRW": { "/dataVolumeContainer": true } #可以看到挂在上了,权限是RW: true,表示可读写容器和宿主机之间数据共享:
[root@localhost ~]$ echo "i 'm in container" > a.log #容器内操作 [root@localhost ~]$ ls -l [root@localhost ~]$ echo "i 'm in container" > a.log #宿主机内操作容器停止退出后,主机修改后数据是否同步:
[root@localhost ~]$ docker attach 容器id 1. 容器先停止退出 2. 主机修改a.log 3. 容器重启进入 4. 查看主机修改过的a.log内容同步经测试发现,即时容器退出,修改宿主机后,会实现同步
命令(带权限) 正常通过以上命令进行添加数据卷,默认权限是 RW:true,即可读写,可以使用以下命令,可以容器数据卷只可以读,即read only
[root@localhost ~]$ docker run -it -v 宿主机目录:容器中目录:ro 镜像名 #ro:表示 read only , 配置后可以在容器中挂载目录下添加文件试试,会提示该目录为只读。在宿主机上新建一个目录
[root@localhost ~]$ mkdir mydockerfile进入目录,新建Dockfile文件,并编辑它
[root@localhost ~]$ cd mydockerfile [root@localhost ~]$ vim dockerfile FROM centos VOLUME ["/test_dockfile_container"] CMD echo "lonely --success" CMD "/bin/bash"可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷
VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]
说明: 出于可移植和分享的考虑,用-v 主机目录:容器目录这种方法不能够直接在Dockerfile中实现。 由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
使用命令docker build 打包构建新镜像
[root@localhost ~]$ docker build -f dockerfile文件目录 -t 镜像名以及版本号 -f :表示Dockfile文件目录 -t:表示镜像名以及版本号. 最后的 . :表示使用当前目录的Dockfile文件进行构建最后面有一个 . 表示在当前目录下,用法列如:
[root@localhost ~]$ docker build -f /mydockerfile/Dockerfile -t lonely/mydockerfile .run 容器:
[root@localhost ~]$ docker run -it 容器id /bin/bash进入容器后,查看是否存在Dockerfile文件中的 VOLUME对应的文件夹
那么对应宿主机目录上那个呢?
进入宿主机中,使用命令 docker inspect 查看绑定的 宿主机目录去查看生成的宿主机挂载目录中 添加一个文件来测试是否挂载成功Docker挂载主机目录Docker访问出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个--privileged=true参数即可
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。 Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。
构建三步骤
编写DockerFile文件 -------->docker build ------>docker run
DockerFile格式:
## Dockerfile文件格式 # This dockerfile uses the ubuntu image # VERSION 2 - EDITION 1 # Author: docker_user # Command format: Instruction [arguments / command] .. # 1、第一行必须指定 基础镜像信息 FROM ubuntu # 2、维护者信息 MAINTAINER docker_user docker_user@email.com # 3、镜像操作指令 RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list RUN apt-get update && apt-get install -y nginx RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf # 4、容器启动执行指令 CMD /usr/sbin/nginx从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料Docker镜像是软件的交付品Docker容器则可以认为是软件的运行态。Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
Docker容器,容器是直接提供服务的。
FROM <image name>,例如 FROM ubuntu
所有的 Dockerfile 都用该以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像;可以在同一个 Dockerfile 中多次使用 FROM 命令用于创建多个镜像。
MAINTAINER <author name>用于指定镜像创建者和联系方式。
例如
MAINTAINER Victor Coisne victor.coisne@dotcloud.comRUN <command>用于容器内部执行命令。 每个RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。
ADD <src> <dst>用于将 文件复制到 文件: 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url, 是容器中的绝对路径。
和run 不同,run 是生成镜像要执行的命令,cmd 是 启动生成后的镜像的时候自动执行的命令。 CMD 命令有三种格式:
CMD ["executable","param1","param2"]:推荐使用的 exec 形式。CMD ["param1","param2"]:无可执行程序形式CMD command param1 param2:shell 形式。CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件:不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为ENTRYPOINT的参数。
一个 Dockerfile 中只能有一个CMD,如果有多个,则最后一个生效。 CMD 的 shell 形式默认调用 /bin/sh -c 执行命令。
CMD命令会被 Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把 CMD 里的命令覆盖。
命令行传入的算是最后一个cmd 命令,最后一个有效。
如果传入的参数里,没有可执行文件,则这些参数就作为entrypoint的参数,
如果传入的参数里,包含可执行文件,则entrypoint 不执行。
docker run busybox 不加启动命令的时候,会执行镜像busybox 默认的启动命令(busybox 也是通过dockerFile 创建的,也可以指定启动执行的命令),这个时候,如果 如果默认命令不包含可执行文件,需要找到entrypoint 作为可执行文件,默认命令作为 参数。
ENTRYPOINT 命令的字面意思是进入点,而功能也恰如其意:他可以让你的容器表现得像一个可执行程序一样。
ENTRYPOINT 命令也有两种格式:
ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 exec 形式 ENTRYPOINT command param1 param2 :shell 形式
一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。
关于 CMD 和 ENTRYPOINT 的联系请看下面的例子 仅仅使用 ENTRYPOINT:
FROM ubuntu ENTRYPOINT ls -l执行 docker run 306cd7e8408b /etc/fstab和 docker run 306cd7e8408b结果并不会有什么差别:
[root@localhost ~]$ docker run 306cd7e8408b /etc/fstab total 64 drwxr-xr-x 2 root root 4096 Mar 20 05:22 bin drwxr-xr-x 2 root root 4096 Apr 10 2014 boot drwxr-xr-x 5 root root 360 Apr 24 02:52 dev drwxr-xr-x 64 root root 4096 Apr 24 02:52 etc drwxr-xr-x 2 root root 4096 Apr 10 2014 home ……但是我们通常使用 ENTRYPOINT 作为容器的入口,使用 CMD 给 ENTRYPOINT增加默认选项:
FROM ubuntu CMD ["-l"] ENTRYPOINT ["ls"]然后执行这个容器: 不加参数便会默认有 -l参数:
[root@localhost ~]$ docker run 89dc7e6d0ac1 total 64 drwxr-xr-x 2 root root 4096 Mar 20 05:22 bin drwxr-xr-x 2 root root 4096 Apr 10 2014 boot drwxr-xr-x 5 root root 360 Apr 24 02:47 dev drwxr-xr-x 64 root root 4096 Apr 24 02:47 etc drwxr-xr-x 2 root root 4096 Apr 10 2014 home drwxr-xr-x 12 root root 4096 Mar 20 05:21 lib drwxr-xr-x 2 root root 4096 Mar 20 05:20 lib64 drwxr-xr-x 2 root root 4096 Mar 20 05:19 media drwxr-xr-x 2 root root 4096 Apr 10 2014 mnt drwxr-xr-x 2 root root 4096 Mar 20 05:19 opt dr-xr-xr-x 386 root root 0 Apr 24 02:47 proc drwx------ 2 root root 4096 Mar 20 05:22 root drwxr-xr-x 7 root root 4096 Mar 20 05:21 run drwxr-xr-x 2 root root 4096 Apr 21 22:18 sbin drwxr-xr-x 2 root root 4096 Mar 20 05:19 srv dr-xr-xr-x 13 root root 0 Apr 24 02:47 sys drwxrwxrwt 2 root root 4096 Mar 20 05:22 tmp drwxr-xr-x 11 root root 4096 Apr 21 22:18 usr drwxr-xr-x 12 root root 4096 Apr 21 22:18 var加了 /etc/fstab参数便会覆盖原有的 -l 参数:
[root@localhost ~]$ docker run 89dc7e6d0ac1 /etc/fstab /etc/fstabEXPOSE <port> [<port>...] 命令用来指定对外开放的端口。 例如 EXPOSE 80 3306,开放 80 和3306 端口。
WORKDIR /path/to/work/dir 配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。 可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。
例如:
FROM ubuntu WORKDIR /etc WORKDIR .. WORKDIR usr WORKDIR lib ENTRYPOINT pwddocker run ID 得到的结果为:/usr/lib
USER <UID/Username> 为容器内指定 CMD RUN ENTRYPOINT 命令运行时的用户名或UID。
VOLUME ['/data']允许容器访问容器的目录、允许容器之间互相访问目录。 VOLUME 仅仅是允许将某一个目录暴露在外面,更多的操作还需要依赖 Docker 命令实现。
更多的内容可以参考 深入理解 Docker Volume(一)
参考 export 的用法咧:
ENV LC_ALL en_US.UTF-8案例:自定义镜像Tomcat9
1、创建目录
[root@localhost ~]$ mkdir -p /mydockerfile/tomcat92、在上述目录下touch c.txt
[root@localhost tomcat9]$ touch c.txt3、将jdk和tomcat安装的压缩包拷贝进上一步目录
[root@localhost tomcat9]$ ls -l/4、在/mydockerfile/tomcat9目录下新建Dockerfile文件
[root@localhost tomcat9]$ vim Dockerfile FROM centos MAINTAINER zzyy<zzyybs@126.com> #把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下 COPY c.txt /usr/local/cincontainer.txt #把java与tomcat添加到容器中 ADD jdk-8u171-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.8.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_171 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin #容器运行时监听的端口 EXPOSE 8080 #启动时运行tomcat # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ]# CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"] CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out [root@localhost tomcat9]#5、构建tomcat9镜像
[root@localhost tomcat9]$ docker build -t wwtomcat9 .查看镜像
[root@localhost tomcat9]$ docker images6、运行tomcat9镜像
[root@localhost tomcat9]$ docker run -d -p 9080:8080 --name myt9 -v /mydockerfile/tomcat9/test:/usr/local/apache-tomcat-9.0.8/webapps/test -v /mydockerfile/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.8/logs --privileged=true zzyytomcat9 038cad9053022a7734e31cc589b1ecd1215cf96142ded6158ec8e2b146214 [root@localhost tomcat9]$ docker psDocker挂载主机目录Docker访问出现cannot open directory .: Permission denied 解决办法:在挂载目录后多加一个--privileged=true参数即可
8、在自定义的tomcat9上发布演示实例
[root@localhost test]$ pwd /mydockerfile/tomcat9/test [root@localhost test]$ mkdir WEB-INF [root@localhost test]$ cd WEB-INF/ [root@localhost WEB-INF] vim web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>test</display-name> </web-app> [root@localhost WEB-INF]# cd .. [root@localhost test]# vim a.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> -----------welcome------------ <%="i am in docker tomcat self "%> <br> <br> <% System.out.println("=============docker tomcat self");%> </body> </html> [root@localhost test]#pwd /mydockerfile/tomcat9/test [root@localhost test]# ll [root@localhost test]$ docker exec 038cad905302 ls -l /usr/local/apache-tomcat-9.0.8/webapps/test因为第6步运行镜像的时候添加了容器卷,所以 在宿主机绝对路径目录/mydockerfile/tomcat9/test下添加文件,会同步到容器内目录 /usr/local/apache-tomcat-9.0.8/webapps/test
docker hub上面查找tomcat镜像
[root@localhost ~]$ docker search tomcat从docker hub上拉取tomcat镜像到本地
[root@localhost ~]$ docker pull tomcatdocker images查看是否有拉取到的tomcat
[root@localhost ~]$ docker images使用tomcat镜像创建容器(也叫运行镜像)
[root@localhost ~]$ docker run -it -p 8080:8080 tomcatdocker hub上面查找mysql镜像
[root@localhost ~]$ docker search mysql从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6
[root@localhost ~]$ docker pull mysql:5.6使用mysql5.6镜像创建容器(也叫运行镜像)
[root@localhost ~]$ docker run -p 12345:3306 --name mysql -v /zzyyuse/mysql/conf:/etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs -v /zzyyuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6 命令说明: -p 12345:3306:将主机的12345端口映射到docker容器的3306端口。 --name mysql:运行服务名字 -v /zzyyuse/mysql/conf:/etc/mysql/conf.d :将主机/zzyyuse/mysql录下的conf/my.cnf 挂载到容器的 /etc/mysql/conf.d -v /zzyyuse/mysql/logs:/logs:将主机/zzyyuse/mysql目录下的 logs 目录挂载到容器的 /logs。 -v /zzyyuse/mysql/data:/var/lib/mysql :将主机/zzyyuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。 -d mysql:5.6 : 后台程序运行mysql5.6数据备份:
[root@localhost ~]$ docker exec myql服务容器ID sh -c 'exec mysqldump --all-databases -uroot -p"123456" ' > /zzyyuse/all-databases.sql