image(镜像)和container(容器):简单的比喻Docker Engine(Docker环境)就像JVM,image就像Class文件,container就像Java对象
通常docker会怎么使用?
在学习过程中容器和虚拟机一起使用的,如下图所示,当然我们也可以直接在物理机上面安装docker环境
这里虚拟机环境的搭建是用vagrant+virtualbox。
先去官网下载virtualbox,因为virtualbox比较常用所以这里不再演示。
然后vagrant到官网进行下载(可以用迅雷下载速度快一些),下载完后傻瓜式安装就行了。(vagrant网上有 教程 这里就不细说)
如下图代表安转成功:
准备好vagrant和virtualbox后,开始基于vagrant+virtualbox定制化自己的centos:
1.vagrant是根据Vagrantfile文件进行centos的安装。
然后新建一个文件夹,用来放vagrantfile文件,然后在这个文件夹下方用管理员权限运行命令行,如下图所示
vagrant init centos/7
这里的centos/7就是vagrant远端镜像仓库的镜像名称或者在本地直接安装好镜像就不用去远端拉去,和maven是一样的道理。
这时候你的文件夹内就会出现vagrantfile文件,这相当于是配置文件
2.根据Vagrantfile文件中的配置,得到定制化的centos7系统。
我们可以打开这个文件进行查看,如下图所示
上面看第13~15行可以看到如果本地有centos/7镜像则用本地的镜像,如果没有的话就会到https://vagrantcloud.com/search上拉去,后面还可以配置其他的,如像第26行网络端口配置等等,上面的教程都有所以不一一解释。
然后在Vagrantfile文件内输入以下配置:
3.这是后你要去网上(http://www.vagrantbox.es/)下载vagrantbox镜像,如下图所示,点击copy然后用迅雷下载就行了。
然后再将镜像添加到本地
vagrant box add centos/7 E:\...... #这里centos/7对应你Vagrantflie文件中config.vm.box的名字,然后E:/....对应你下载vagrantfile镜像所存放的路径
vagrant box list #查看你当前有什么镜像
4.准备好镜像后,就开始用该镜像进行安装centos,如下图所示,安装后你的virtualbox中就会显示
5.进入虚拟机,当然你也可以用其他方式进入,例如xshell等待(默认账号密码都为vagrant)。
如果要用xshell连接的话,设置如下两个图所示,账号密码都为vagrant,你也可以对网络ip、端口、账号密码进行就改。
以上环境就准备好了,接下来就是准备docker
docker产品手册 ,在这里你可以查询到安装使用等一些教程,可以参考进行使用,下面大致讲一下流程:
这里要说明一下:我目前学习docker遇到的很多问题是权限问题和网络问题,权限问题一般在执行命令前面加上sudo就可以解决,网络问题主要是因为docker一些官方链接国内访问不到要就行一些修改
如果之前有安装过docker先删除掉
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装依赖
sudo yum install -y yum-utils
设置仓库(注意这里把场库设置成阿里云的,官方的仓库源因为在国内访问不到)
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装docker,这时候就会到上面设置的阿里云仓库里面进行安装,安装过程有两次要输入,第一次输入y;第二次输入j
sudo yum install docker-ce docker-ce-cli containerd.io
然后启动docker
sudo systemctl start docker
还可以设置开机启动
sudo systemctl enable docker
停止docker
sudo systemctl stop docker
启动成功后尝试一下docker是否成功
sudo docker run hello-world
首先会提示你本地镜像仓库中没有hello-world镜像,所以会到远程仓库中拉去,但是报了错误,这是因为外国官方源国内没法连接上,具体看这里的 解决方法 ,下载过慢也可以用这里面的方法解决。
按照上面的解决方法后执行后再进行测试,如下图所示:
查看本地镜像也可以看到多出一个文件,这就代表docker安装成功
这里说明一下
sudo docker images 查看本地所有镜像
sudo docker ps 查看运行的容器
sudo docker ps -a 查看所有容器
由上图可以知道hello-world容器运行后就关闭了,所以只能在sudo docker ps -a中看到。
镜像和容器这里大致解释一下,本地镜像就好像一个程序的安装包,然后安装后变成的程序就好像是容器,所以上面的流程大致就是我们运行hello-world容器时,系统发现本地没有hello-world容器,所以系统自动去线上拉去镜像到本地,然后根据镜像启动容器,hello-world容器启动运行后自动关闭。
由上面我们已经大致了解了docker 了,现在先讲一下Images(镜像)。
从上面的hello-world例子我们知道可以从远端仓库拉去镜像,这时候我们可以去 Docker Hub 查看所有的镜像,如下图所示:
这里就查出hello-world的镜像,你还可以查JDK、MySQL、Tomcat、Redis、Nginx等等。
下图为redis,下图第一个下载数最多的redis为官方的,下面其他的为别人在官方的基础上自定义的,增加了自己的一些设定等等。
然后我们点击第一个官方,进入后我们可以看到版本等等一些信息,其中latest代表最新的版本
当然我们还可以通过下面的命令去查询
sudo docker search XXX
然后我们可以通过sudo docker pull XXX
把镜像从远端仓库拉去下来,如下图所示,如果直接sudo docker pull mysql
则代表把最新版本的拉去下来,如果后面有加版本号则代表拉去指定的版本。
镜像的操作命令如下图所示,我们还可以对镜像进行删除等操作,这里就不再演示:
操作 | 命令 |
---|---|
检索 | sudo docker search 关键字 eg:docker search mysql |
拉去 | sudo docker pull 镜像名:tag(不加tag表示用最新版本) |
列表 | sudo docker images或sudo docker image ls |
删除 | sudo docker rmi 镜像id/镜像名(删除的镜像不能有相关容器存在) |
如果有了image(镜像),那么就可以基于image(镜像)创建container(容器)
容器的操作相对于镜像会麻烦一些,因为不同的容器执行的命令会有所不同,因为不同容器执行的命令中参数会有一定的差别。具体命令可以参考官方:https://docs.docker.com/reference/
这里先展示几个比较常见的命令,上文也出现过的:
sudo docker ps 查看运行中的容器
sudo docker ps -a 查看所有容器
sudo docker start 容器id 启动容器
sudo docker stop 容器id 停止容器
sudo docker rm -f 容器id 删除容器
然后是容器创建的命令,这个复杂一点,因为不同的容器参数不一样,具体可以查看上面的官方参考
大致的命令为
docker run 参数 参数值
例如tomcat可以为
docker run --name mytomcat -d tomcat 这里就表示用名为tomcat的镜像创建名为mytomcat的容器,-d表示后台运行,可去掉就变成前台运行。
而mysql的命令就变成
docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
或
docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql
这里mysql如果和上面tomcat一样的写法就会出错(运行后自动退出),这是因为没有设定密码。
另外如果你发现出错了,但是不知道为什么可以通过 docker logs 容器id 查看错误
端口说明
另外上面的参数出现了端口号,例如docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
中的-p 3306:3306
这里表示宿主机的3306端口(冒号前)映射到容器内容的3306端口(冒号后),具体可以参考:Docker容器内部端口映射到外部宿主机端口 - 运维笔记
上面说的宿主机表示centos7这个虚拟机,而不是物理主机,其实容器也是一个linux系统,自然而然我们也可以进入到容器中
进入到指定的容器中
sudo docker exec -it 容器id/容器名称 bash
在mysql的docker容器中我们可以查看它的目录发现其实和centos虚拟机的目录是一样的,也是一个linux目录
从上面可以知道docker容器中也相当于一个linux系统,所以docker容器也有它自己的ip地址等,用一种查询方法是用上面的命令进入容器中然后跟在centos一样去使用这个docker容器,例如输入ip addr
就可以查询出来这个docker容器的ip地址,但是要注意,docker安装好后是一个简易的linux系统,所以很多命令没有安装,如果你要去用上面ip addr
进行查询的话会提示你-bash:ip:command not found
,所以我们用简单一点的方法在容器外面进行查询,你可以自己尝试把docker容器的命令安装好然后再内部进行一些操作,网上也有教程这里就不演示(过程会麻烦一些,因为好多命令都得安装)。
sudo docker inspect 容器名称或容器id 就可以查询到关于容器的一些信息
然后我们尝试在centos上对docker容器的id进行ping,也发现ping得通
所以从上面得例子我们可以知道镜像和容器其实底层都是linux操作系统,只不过image只能读,而container读写都可以,container是在image的基础上运行的一个个可读可写的环境。
我们从前面已经大概了解到了两者的关系,这里再简述两者之间一些其他的关系
sudo docker container commit 容器id/容器名称
或者
sudo docker container commit 容器id/容器名称 设定新生成的镜像名称
我们进入官方的github拿去我们想要的Dockerfile文件
点击mysql,进入后如下图所示:
选择5.7版本就可以看到相关的Dockerfile文件,进入后把里面的内容考取出来
这里以mysql来简略的讲视一下Dockerfile中的含含义,具体可以看官方文档https://docs.docker.com/engine/reference/builder/或者网上的教程https://www.runoob.com/docker/docker-dockerfile.html
FROM debian:buster-slim #From 制作该image的基础镜像 layer
RUN groupadd -r mysql && useradd -r -g mysql mysql #运行一条指令,并且表示新的layer层的创建
ENV GOSU_VERSION 1.12 #常量的设置
VOLUME /var/lib/mysql #mysql数据库数据再容器linux系统中所在的目录
COPY docker-entrypoint.sh /usr/local/bin/ #表示从前一个文件拷贝到后一个目录
ENTRYPOINT ["docker-entrypoint.sh"] #设置容器启动时运行的指令
CMD ["catalina.sh","run"] #设置容器启动时运行的指令,加参数
EXPOSE 3306 33060 #暴露在外面的端口是什么
然后我们尝试一下用Dockerfile来创建image
开始构建镜像,其实这里的原理和上面用容器生产镜像是一样的道理
构建成功,查看镜像并用镜像来运行容器,查看生成的容器
上文我们已经讲述了可以用Dockerfile来创建自定义的image了,我们也可以将我们自定义的镜像共享给别人,同时我们也可以将我们的image存储起来。这就需要我们来搭建自己的image仓库。
这里原理其实和github一样。我们可以在docker hub上面注册一个账号,然后通过我们的账号把我们的自定义镜像存储上去,这样别人也就可以在上面获取我们自定义的镜像了。
因为docker hub国内使用比较慢,我也经常会连接不上,必须用,所以这里就不进行演示,主要给些命令
首先你必须要有docker hub的账号
然后你在你本地的centos上用该账号密码和docker hub关联
sudo docker login
然后会让你输入用户名和密码
然后把你想要放到远端仓库的镜像push上去
sudo docker push XXXX
注意你要push上去的镜像名称有规定,必须是“你的账户名/镜像名”这种格式
你可以用下面的语句复制出另起名的镜像
sudo docker tag XXX 你的账户名/XXX
如下图所示,itcrazy2018/new-centos是由new-centos复制出来的,然后你可以把原来的new-centos删除点就行了
然后你可以用sudo docker pull 账户名/镜像名
把你上传的镜像从新拉去下来
docker网络其实主要涉及ip和端口问题,上面已经讲过端口映射的问题,这里再次系统的整理一遍。
我们查看宿主机的ip,发现多了一个docker0网卡,该网卡的作用是和其他docker容器连接,我们前面已经提到过了其他docker容器的ip地址为172.17.0.2、172.17.0.3…等等,他们和宿主机在同个网段,所以互相ping的通。
但是我们的物理机window想要访问我们宿主机centos里面的容器的画也必须要保证物理机能ping的通宿主机,则时候我们就应该设置虚拟机网络为桥接的模式,做如下设置:
做完上面的设置后,我们就可以在物理机上访问虚拟机的docker端口了,例如你虚拟机中的tomcat容器ip地址为172.17.0.2,端口映射为8888:8080 (上文讲过,即虚拟机的8888端口对应tomcat容器的8080端口)
所以你可以在虚拟机中用localhost:8888或者172.17.0.2:8080访问到tomcat内容
你也可以在物理机中用192.168.0.124:8888访问到tomcat内容
所以我们可以从上面所述的知道虚拟机和docker容器的连接方式为桥接的方式。
同时我们也可以自己来设置docker网络
比如我们想要部署tomcat集群,我们可以设定下面的网络
sudo docker network create --subnet=tomcat-net 172.18.0.1/24
如下图设置自己的网段
然后还可以用下面的命令查看网段信息(上面有使用同样的命令过来查询容器网络信息),可以看到有这个网段
sudo docker network inspect tomcat-net
另外我们也可以用sudo docker logs 容器名
来查看启动日志
然后我们可以用下面的语句来指定容器用上面设置的网段
sudo docker run -d -it --name tomcat --net=tomcat-net tomcat
如下图所示
以上都为单机形式,单机网络连接有三种:bridge、host、none
多机形式则有overlay network,这里就不再演示了,可以自行了解
我们知道容器如果删除销毁了,容器里面的数据就会消失,这样是不可靠的。这一节就是讲docker容器的数据持久化问题,
我们可以将数据保存到centos虚拟机中来保持数据持久化。
在centos中新建一个目录volume来存放数据,这里volume是可以让容器创建的时候可以使用这个volume文件
sudo docker volume create --name v1
查看一下当前v1的信息
sudo docker volume inspect v1
然后我们以mysql为例子,可以用以下的语句来创建MySQL容器
sudo docker run -d -p 3307:3306 -v v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --privileged --name mysql1 mysql:5.7
上面主要说两个,第一 -v表示希望把docker容器中/var/lib/mysql文件中的数据映射到虚拟机v1文件中(v1为上文所创建的,容器数据存储/var/lib/mysql中);第二 --privileged表示希望这mysql为最高优先级
然后我们可以像下图一样操作,发现容器和虚拟机两个文件内容一模一样
所以容器删除掉数据还是可以持久化保存的。
这时候可以做一个实验,在上述容器中的数据库创建一个表,然后在表中加入数据,然后再把这个容器删除。虽然容器被删除掉数据自然也不存在docker中,但是所有数据还是保存再centos的v1中,这个时候我们可以新建一个mysql容器(注意:创建这个新的容器也要用-v v1:/var/lib/mysql参数,这样新的数据库就的数据就可以和v1互通),然后我们就会发现新的数据库中存在之前旧的数据库的数据(之前旧数据库创建的那个表)。
从上面的知识我们已经大致学会使用docker,但是如果我们要使用多个容器,还要进行一些特定网络的设定等等一些操作,操作起来还是十分麻烦和混乱,而且也不知道容器与容器之间的关系。
所以我们可以使用Docker Compose来帮助我们维护这些容器。
docker compose使用起来和上面的dockerfile还是很相似的,主要是维护docker-compose.yml文件,因为个人时间有限所以就不这里扩充了,我推荐可以看官网的手册和菜鸟教程进行学习。
总结: 学到这里其实已经基本了解了docker的入门知识,但是还是有许多东西可以深入的了解自学一下,docker容器技术的运用十分广泛,包括docker容器搭建微服务架构、CICD等等,大家有空可以去自学。有什么问题欢迎留言讨论,谢谢。