-
核心思想: 一次构建,处处运行.
-
背景
- 在服务器上部署一个应用的运行环境,即使开发提供了所有了代码、配置文件、软件环境等,还是往往出现部署失败的情况,并且浪费大量时间.
- docker镜像的设计,打破过去程序即应用的观念,透过镜像(images)将作业系统核心(内核)除外,从系统环境开始,由底至上打包应用,达到应用程式跨平台间的无缝接轨运作.docker是一个解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟技术.
- 传统的虚拟化方式的缺点
- 资源占用多
- 冗余步骤多
- 启动慢
- 传统的虚拟化方式及与和Docker区别
- 传统的虚拟化技术是在虚拟出一套硬件后,在其上运行一个完整的操作系统,在该系统上再运行所需应用进程.
- Docker容器内的应用进程直接运行于宿主的内核,docker容器内没有自己的内核,而且也没有进行硬件虚拟,因此docker容器要比传统虚拟机更为轻便.
- 每个docker容器之间互相隔离,每个容器都有自己的文件系统,容器之间进程不会互相影响,能区分计算资源.
- docker的组成部分
- 镜像: 将应用程序和配置依赖打包好形成的一个可交付的运行环境.
- 容器: 可以把容器看作是一个简易的linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序.
- 仓库: 集中存放镜像文件的地方.
镜像就是一个只读的模版,容器是镜像的一个实例.
容器和镜像都是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的.
-
仓库和仓库注册服务器的区别
仓库注册服务器上往往存放着多个仓库,每个仓库中又包含多个镜像,每个镜像有不同的标签(类似于版本号). -
docker run命令
eg: docker run hello-world
作用: 看本机上有没有hello-world镜像,有的话就生成一个hello-world容器实例,并在该容器中运行命令.
Docker run流程图:
-
Docker是怎么工作的
Docker使一个client-server结构的系统,Docker守护进程(daemon)运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器(一个包含应用程序的运行时环境,即鲸鱼上的集装箱). -
Docker为什么比VM快
- docker有比虚拟机更少的抽象层.由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源.因此在CPU、内存利用率上docker将会在效率上更有优势.
- docker利用的是宿主机的内核,而不需要在宿主机上再创建一个操作系统.因此当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核.所以虚拟机的新建过程是分钟级的,而docker直接利用宿主的操作系统,新建过程只需要几秒钟.
-
UnionFS联合文件系统
Union文件系统(Union FS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的累加,同时可以将不同目录挂载到同一个虚拟文件系统下.Union文件系统是Docker镜像的基础,镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像.
特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录. -
Docker镜像加载原理
docker的镜像实际上是由一层一层的文件系统组成,这样的层级文件系统称为UnionFS.
示例图:
-
为什么Docker镜像要采用这种分层结构?
最大的好处是共享资源.
比如有多个镜像都是从相同的base镜像构建而来,那么宿主机中只需要保存一份base镜像即可. 同时内存中也只需要加载一份base镜像,就可以为所有的容器服务了,镜像的每一层都可以被共享. -
为什么虚拟机中的centos等操作系统都是好几个G,但是docker中的centos才200M?
- 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等.
- 底层直接使用的主机host的内核,自己只需要提供rootfs就可以了.同时对于一个精简的os,rootfs只包括最基本的命令、工具和程序库就可以了.
- docker容器数据卷
- 作用: 数据的持久化,完全独立于容器的生存周期,因此docker不会在容器删除时删除其挂载的数据卷.
- 卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但是不属于UnionFS,因此能够绕过UnionFS提供一些用于持久化存储或共享数据的特性.
- 特点
数据卷可以在容器之间共享或重用数据.
卷中的更改可以直接生效
数据卷中的更改不会包含在镜像的更新中
数据卷的生命周期一直持续到没有容器使用它为止. - 几个命令
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
结果: 两个目录文件内容一致,宿主机和容器都可以对数据卷读写.
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
结果: 两个目录文件内容一致,但是容器数据卷只读,不能写(即不能修改文件和添加文件).
-
数据卷容器
命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器称为数据卷容器. -
dockerfile
定义: 构建docker镜像的构建文件,是由一系列命令和参数构成的脚本.
- 每条保留字指令都必须为大写字母并且后面跟随至少一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
- docker执行dockerfile的大致流程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成.
- Dockerfile、Docker镜像、Docker容器的关系
- Dockerfile是软件的原材料
- Docker镜像是软件的交付品
- Docker容器可看作是软件的运行态
- Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署和运维,三者缺一不可,合力充当Docker体系的基石.
- docker在centos系统上的安装
-
卸载docker
$ sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
-
安装yum工具包
$ sudo yum install -y yum-utils
-
配置docker仓库
$ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
-
安装最新版本docker引擎和容器
$ sudo yum install docker-ce docker-ce-cli containerd.io
-
查看docker是否安装及安装版本
$ docker --version
-
centos配置docker阿里云镜像加速
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://qd9dsp0q.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
-
docker常用命令
- 启动: sudo systemctl start docker
mac下打开鲸鱼🐳application即可 - 设置docker开机自启动 sudo systemctl enable docker
- docker search image_name 搜索镜像源
- 拉取镜像: docker pull image_name 默认拉取最新的,也可以指定版本
- 查看镜像: docker image ls
- 查看正在运行容器: docker ps
- 查看所有容器(包括关闭的): docker ps -a
- 第一次运行镜像创建容器并指定映射端口: docker run -itd --name redis(容器名) -p 6379:6379 redis
- 启动关闭的容器: docker start container_id
- 进入正在运行的容器: docker exec -it container_id /bin/bash(即执行start命令后才能执行该命令,使用run命令可以直接进入容器中)
- 容器开机自启动: docker update container_id/name --restart=always
- 关闭容器: docker stop container_id
- 删除容器: docker rm container_id
- 删除镜像: docker rmi image_id / image_name
- 创建并使用redis容器示例:
- 快速启动:
- 配置文件启动及挂载文件:
redis容器的/etc/redis目录下没有redis.conf文件,如果直接执行创建redis容器命令,会将本机redis.conf当作文件夹看待.需要先创建该文件# 创建文件夹和文件 sudo mkdir -p /usr/local/docker/redis/ sudo touch /usr/local/docker/redis/redis.conf` # 创建redis容器 sudo docker run -p 6379:6379 --name myredis -v /usr/local/docker/redis/redis.conf:/etc/redis/redis.conf -v /usr/local/docker/redis/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes # 设置AOF持久化也可以在redis.conf文件中添加appendonly yes,然后以配置文件方式启动redis
- 快速启动:
- docker创建mysql容器
-
拉取mysql镜像
sudo docker pull mysql:5.7
-
创建mysql容器
sudo docker run -p 3306:3306 --name mysql -v /mydata/mysql/log:/var/log/mysql -v /mydata/mysql/data:/var/lib/mysql -v /mydata/mysql/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
-
修改mysql默认编码(
sudo vim /mydata/mysql/conf/my.cnf
)[client] default-character-set=utf8 [mysql] default-character-set=utf8 [mysqld] init_connect='SET collation_connection = utf8_unicode_ci' init_connect='SET NAMES utf8' character-set-server=utf8 collation-server=utf8_unicode_ci skip-character-set-client-handshake skip-name-resolve
-
进入到mysql容器中
sudo docker exec -it mysql /bin/bash
-
在
/etc/mysql
中可以看到存在my.cnf文件,可通过cat命令查看
-
进入mysql执行mysql语句
mysql -uroot -p
-
从容器中退出
quit / exit