一篇文章上手docker(原理,部署,使用,坑)
(一)定义与介绍
前言:与虚拟机技术比较:
虚拟机(VM):在docker容器技术出现之前使用的是虚拟机技术,将一台物理机虚拟化为多台机器,可搭载不同的操作系统。但每一个虚拟机系统的消耗较大,都需安装一个完整的内核,存储空间占用也多。且系统镜像也不支持版本控制。
Docker容器技术:docker的一大特点就是简单轻便,物理机(宿主机)只需要安装docker环境,拉取image镜像,则可以通过该镜像创建一个或多个系统实例(Docker称为容器,容器间相互隔离互不影响),且image镜像与虚拟机的系统镜像相比十分小。除此之外,镜像支持版本控制,Docker可以将容器进行commit提交形成一个新的镜像,可push到远端仓库,私人备份或公有到image仓库中。对于项目开发而言,idea可以配置dockerfile实现Java项目的自动化部署。
4大概念:容器(Container),镜像(Images),仓库(Repository),宿主机(物理机)
仓库Repository:可指定配置源,是镜像存储的地方,可从此处拉取镜像(pull),或者将本地的镜像进行提交(push)
镜像Image:系统或环境的镜像文件,可由其创建并运行(run)出容器实例(container)。镜像可从仓库拉取(pull)获得,或者从现有容器commit提交得到一份新的镜像Image
容器Container:由镜像创建的容器实例,初始状态下各个容器实例环境相同,互不影响。容器分为两个状态:运行和停止
宿主机(物理机):即就是运行docker环境的这台物理机
从公有仓库拉取的镜像可以进行自定义化,然后发布到公有仓库,或是自己的私有仓库上。
同一份镜像可以产生多个容器(实例),且这些容器初始环境完全相同,且互不影响,相互隔离(文件,ip等,进程)
(二)Docker环境配置
镜像源指定:为了下载更快,可指定为阿里云(将会影响docker search的结果和docker pull的速度)
阿里源Docker服务网站:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台
"registry-mirrors": [
"https://8rzbqaxd.mirror.aliyuncs.com"
],
Windows下直接安装Docker Desktop即可
注意:
由于win10新版本提供了wsl2版的Linux,即Windows自带一个Linux内核,若Docker开启了wsl2的支持,则高级配置不会展示出:CPU,内存,磁盘,容器磁盘镜像目录等配置项。
Resources-Advance选项卡指定容器的配置,以及生成容器Container的磁盘镜像位置vhdx
Resources-File Sharing选项卡指定共享文件夹,即将宿主机(物理机)的某些目录用来挂载到容器中,可供容器使用
在Windows下的docker提供了两种container模式,可通过右键进行切换:但优先选择LinuxContainer
LinuxContainer:可运行基于Linux内核和Windows内核的容器(运用Hyper-V技术)
WindowsConainer:仅可运行基于Windows内核的容器
Image镜像的下载目录在windows平台下不方便配置,因为在LinuxContainer模式下,镜像Image文件都是下载到一个虚拟的Linux目录中的(通过docker info命令可查),若为WindowsContainer模式,则可以配置。
Linux Ubuntu(18.04)下:
#若存在老版本先卸载之前的sudo apt-get remove docker docker-engine docker.io containerd runc#更新源sudo apt-get update#安装curl工具sudo apt-get install curl#添加docker的GPG密钥curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -#验证密钥sudo apt-key fingerprint 0EBFCD88#安装添加源工具sudo apt install software-properties-common#指定仓库sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"#再次更新源sudo apt-get update#安装docker-ce(社区版),cli客户端,以及解耦apisudo apt-get install docker-ce docker-ce-cli containerd.io
验证docker环境:
docker -v
#或者
systemctl status docker
Ubuntu版的docker配置:
全局配置文件在:/etc/default/docker
sudo vim /etc/default/docker
修改镜像下载目录与修改容器磁盘镜像文件目录
默认配置可以通过docker info命令查看
该文件夹包含了下载的image和container文件夹
若需要修改,则要修改:/etc/systemd/system/multi-user.target.wants/docker.service文件
sudo vim /etc/systemd/system/multi-user.target.wants/docker.service
修改为其他位置即可
配置阿里源:创建/etc/docker/daemon.json,并写入以下内容:然后重启服务systemctl restart docker
{
"registry-mirrors": [
"https://8rzbqaxd.mirror.aliyuncs.com"
]
}
(三)基本Docker命令
镜像Images相关 (镜像名要求全小写)【一般为docker image xxx】
#获取当前所配置的源下,与输入的关键字相关的可提供下载的镜像(存放在远端的仓库)
docker search <关键字>
#按版本筛选(加标签)
docker search <关键字>:<tag>
例:docker search centos,docker search ubuntu:18.04
其中offical代表官方,automated代表自动构建产生的镜像
注意:官方镜像系统内容很少,有时缺少基本工具,如:ifconfig,ping,sudo之类,需要运行容器后自己安装
#拉取镜像
docker image pull <imageName/imageID>
#拉取镜像(指定版本),需到其官网查看他在docker hub上该版本的tag
docker image pull <imageName>:<tag>
#将镜像推送到远端仓库(imageName要求包含远端仓库地址)
docker image push <imageName>:<tag>
#查看所有已有的镜像
docker image ls
#创建容器并运行(最基础的)(可指定tag)
docker run --name <newContainerName> <imageName>:<tag>
#删除已有镜像(tag不为latest时,需要指定tag)【确保无本镜像创建的container】
docker image rm <imageName>
#镜像重命名
#此时会生成一个id相同的新镜像,手动删除之前不要的即可(可指定tag)
docker image tag <imageName> <newImageName>
#查看镜像详细信息(可指定tag)
docker image inspect <imageName>
容器Container相关【一般为docker container xxx】
#查看容器列表(正在运行的)
docker container ls
#查看容器列表(所有的)
docker container ls -a
#运行已存在的容器
docker container start <containerName>
#停止某个运行的容器
docker container stop <containerName>
#重启某个容器
docker container restart <containerName>
#删除某个容器(确保该容器已停止运行)
docker container rm <containerName>
#容器重命名
docker container rename <containerName> <newName>
#进入某一正在运行容器(终端模式)
docker container exec -it <containerName> /bin/bash
#退出某容器(在容器终端中执行)
exit
#查看容器的占用情况(实时占用情况[CPU,RAM,NET])
docker container stats <containerName>
#查看某容器的详细信息(端口映射,磁盘映射,虚拟网段IP,维护者等等)
docker container inspect <containerName>
(四)容器的网络/存储隔离以及共享目录的配置
以下操作与image镜像本身无关,都是在执行run命令时配置(run配置参数只跟container实例,与image镜像无关)
网络隔离(下能通上,上不通下【与路由器以路由方式嵌套理解相同】)
容器间网络互通(不管是不是由同一镜像产生的容器实例),因为他们在同一个虚拟网段下(默认在172.17.0.1),且这些容器都可以ping通宿主机(物理机)也可以通过物理机连接互联网(因为访问上层网络没有问题),但对于宿主机来说,其无法直接访问(ping通)任何一个容器,因为虚拟网段是模拟出来的,他是宿主机所在的下一级网段,没办法直接访问。
【这点和路由器之间以路由模式相接相同,假如192.168.1.1为一个路由,192.168.1.2为子路由,他的网关地址为192.168.123.1,其存在2个主机:192.168.123.2与192.168.123.3,此处通过192.168.1.x的主机直接直接访问192.168.123.x不可能访问成功,因为路由访问只能访问同级和上级的网络,只能访问192.168.123.x所属的上层网络ip:192.168.1.2,由该路由器配置DMZ/端口映射到其子层网络】
查看容器所在网段配置(类似于172.17.0.X)
docker network inspect bridge
【解决方案:对容器开启端口映射】
因此为了能让宿主机能访问【必然如此,不然在容器里运行的服务暴露不出来】,docker在执行run命令的时候提供了可配置的参数
#指定单个端口
docker run -dit --name <想取的容器名> -p <宿主机端口>:<容器内服务端口> <镜像名>
#指定多个端口
docker run -dit --name <想取的容器名> -p <宿主机端口>:<容器内服务端口> -p <宿主机端口>:<容器内服务端口> <镜像名>
注意:
只能在首次创建容器运行时(docker run命令)候指定端口映射,已有的容器无法添加
指定端口映射创建出来的容器container以后就直接启动,无需再次指定端口,只需确保宿主机端口未被占用即可开启
若实在要对已有容器container添加/修改端口映射,只能将当前容器提交commit为一个新的镜像,然后再用该镜像run一个新的容器(此时指定端口映射)
docker container commit <containerName> <newImageName>
存储隔离
Docker容器Container实例之间的存储是相互隔离,互不影响的,容器Container产生的文件叫做磁盘镜像文件(DiskImage)这点和虚拟机相同,他的位置根据之前在DiskImageLocation目录:vhdx文件大小上限可以配置。默认64GB,所有容器Container实例的数据都存在这一个磁盘镜像文件中
共享目录配置
Docker容器可共享使用宿主机(物理机)中的某一文件目录,该文件目录需要事先配置为共享文件夹,然后在首次创建并运行容器时追加-v参数进行指定(与端口映射相同,只能在这个时机指定)
[Windows指定共享目录]
(本步骤是对windows文件夹的权限指定,即让docker拥有以下文件夹权限)
[Linux(Ubuntu)指定共享目录]
无需额外配置,只需在docker run时指定-v参数即可
【磁盘映射参数(也可指定多个)】
#-v <宿主机目录>:<容器环境需要挂载的地方>
#例
docker run -dit --name testMultiFolderMapping -v E:/DockerShareFolder:/mnt/folder1 -v E:/Share:/mnt/folder2 ercircle/ubuntu_server
超级权限(一般不需要)
在首次创建并运行run容器container实例时,添加以下参数:--privileged=true可以配置容器内环境具备超级管理员的权限。甚至允许在容器中再次搭建docker
--privileged=true
#例
docker run -dit --name Test --privileged=true ercircle/ubuntu_server
指定时区(可安装后提交为镜像,以后直接使用这个镜像)
容器时间默认和宿主机相同,但时区使用的是UTC+0即太平洋时区,要改为东八区,由于docker容器的权限有限,需要安装tzdata来调整
sudo apt-get install tzdata
配置某一容器自动启动
可以在首次docker run时追加参数,也可以对已有的container进行设置
#首次运行时指定该容器实例自启
docker run --restart=always
#对已有的容器设置为自启
docker update --restart=always <CONTAINER ID>
(五)修改Docker镜像并push至库
核心概念:
镜像的仓库没有版本控制,每一次提交都是一个新的镜像,新的镜像和之前没有关系(imageName相同,tag不同也算是不同的image)
镜像Image本身不可修改,所谓的修改是对其生成的容器Container实例进行操作后,提交commit后为一个新的镜像
提交Commit命令:
#对于某镜像的容器实例修改后提交为一个新的镜像(镜像名可与之前的相同(但此时必须指定tag【一般设置为版本号】))
docker container commit -m "本次提交内容" -a "作者信息" <containerName> <newImageName>:<可指定tag(代表版本)>
配置阿里云镜像管理服务:
将自己的镜像push到阿里云镜像管理服务中(自己的远端镜像仓库)
官网:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台
(1)准备工作:配置账户密码,创建命令空间,确定好地域节点名
(2)创建命名空间,创建镜像仓库(使用本地仓库模式)
(3)执行docker命令登录到目标节点:
docker login --username=五航战瑞鹤酱 registry.cn-shanghai.aliyuncs.com
(4)列出本地镜像,确定要提交的镜像id或者名字,执行tag操作修改image名
Tag后原image不影响,依然存在,会产生一个imageId相同,imageName为新设置的镜像,新设置的镜像name需要指定为固定格式:地域节点/com/命名空间/镜像仓库名:,tag一般指定为版本号
docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/zuikaku/pilipili-web-ubuntu:1.0
(5)执行提交push操作
docker push registry.cn-shanghai.aliyuncs.com/zuikaku/pilipili-web-ubuntu:1.0
push完成后,在镜像版本中可以看到这次push的记录,未指定tag,则默认为latest(最新的)
如果后续需要拉取,则到基本信息中:执行docker pull
docker pull registry.cn-shanghai.aliyuncs.com/zuikaku/init-ubuntu:<镜像版本号>
(六)在项目中使用dockerfile实现自动化部署
[1]修改docker.service
Ubuntu版的docker目录在:/etc/systemd/system/multi-user.target.wants/docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
修改完后重新应用
systemctl daemon-reload systemctl restart docker
访问2375端口进行验证
[2]项目中配置docker
pom.xml添加docker的maven插件依赖
<!--使用docker-maven-plugin插件--><plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>1.0.0</version><configuration><!--指定生成的镜像名--><imageName>nanoda/${project.artifactId}</imageName><!--指定标签(一般为版本)--><imageTags><imageTag>1.2</imageTag></imageTags><!-- 指定 Dockerfile 路径:项目根目录--><dockerDirectory>${project.basedir}</dockerDirectory><!--指定远程 docker api地址--><dockerHost>http://www.zuikakuedu.top:2375</dockerHost></configuration></plugin>
项目根目录添加Dockerfile文件
Dockerfile的组成成分:
#指定以哪个image作为初始镜像(此处可指定为公有仓库链接)【推荐先在宿主机把该image事先pull下来,避免docker build时因权限不足的报错】
FROM <镜像远端地址>
#指定该镜像的维护者信息
MAINTAINER <维护者姓名> <联系邮箱(可选)>
#添加哪些文件到目标镜像的目录(一般添加jar包,为tar时会自动解压,镜像环境的目录不存在时会自动创建)
ADD <以项目目录根目录下的文件或目录(相对路径)> <镜像环境的目标目录(绝对路径)>
#指定需要在目标镜像产生的容器中执行的初始化操作(可按顺序指定多条)
RUN <Linux命令1>
RUN <Linux命令2>
#指定需要暴露的端口(仅声明要暴露的端口,方便-P自动映射,手动映射依然需要在run时指定-p参数)
EXPOSE <端口1> <端口2>
#指定挂载点,自动实现路径映射,宿主机地址为随机生成(可通过docker container inspect查看,若要手动指定需要run时指定-v参数)
VOLUME ["/mnt/folder1","/mnt/folder2"]
#指定环境,如JDK,Tomcat目录,编码环境等
ENV LANG C.UTF-8
#指定容器创建完成的运行的命令,容器从关闭状态变为启动后执行的命令(一般用于启动某程序,或者执行某shell)
ENTRYPOINT ["Linux命令","参数1","参数2",...]
案例:
FROM registry.cn-shanghai.aliyuncs.com/zuikaku/ubuntu1804-init-env:1.0
MAINTAINER nanoda tanyu159@live.com
ADD target/oc-0.0.1-SNAPSHOT.jar /home/admin/ZuikakuOnlineCourse/oc.jar
RUN mkdir /home/admin/ZuikakuOnlineCourse/storage
EXPOSE 9091
ENV LANG C.UTF-8
ENTRYPOINT ["nohup","java","-jar","/home/admin/ZuikakuOnlineCourse/oc.jar",">log.txt","&"]
【3】先执行项目package打包
Maven-Package执行打包生成target,确认jar包存在
【4】再执行docker build操作(如果需要重新build,需先进行maven-clean重新打包在docker build,清除docker的一些临时文件)
【5】回到宿主机docker run该新镜像
docker run -dit --name zuikaku-oc -p 9091:9091 -v /home/admin/ZuikakuOnlineCourse/storage/:/home/admin/ZuikakuOnlineCourse/storage nanoda/oc:1.1
特别注意:
可以发现,在进行docker自动化部署,开启2375端口,在项目中指定目标地址:端口,直接执行docker build命令是没有任何身份验证的,这也就说明存在漏洞,黑客可以扫描公网ip及其该端口注入内容,因此2375端口不应在公网开启,仅在局域网内访问,应该挂入vpn或者使用堡垒机的方式进行网络连接,实现docker build
(7)docker可视化管理工具portainer
portainer提供了一种可视化管理docker的方式,本质是一个网页后台,其本身也是作为docker的image存在,使用流程如下:
【1】搜索该镜像:docker search portainer
【2】拉取该镜像:docker image pull portainer/portainer
【3】运行该镜像:需指定端口映射,容器内端口为9000,并开启超级权限和目录映射
docker run -d --name portainerUI -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
【4】放开防火墙,在外网访问该服务
更多教程,可见我的官方网站:最咔酷线上教程:www.zuikakuedu.cn
一篇文章上手docker(原理,部署,使用,坑)相关推荐
- 看菜鸟如何用一篇文章学Docker(超详细)
文章目录 Docker镜像加载原理 Docker常用的命令 关于容器命令 其他常用命令 进入当前正在运行的容器 docker容器文件移动复制 docker 安装测试命令 commit镜像 安装可视化工 ...
- 一篇文章理解Promise原理
前提掌握知识: 微任务包括: MutationObserver.Promise.then()或reject().Promise为基础开发的其它技术,比如fetch API.V8的垃圾回收过程.Node ...
- 一篇文章上手SSH开发,单表全过程,全代码
1 SSH项目的一些部署 1.1 项目目标与版本介绍 1.2 SSH知识分析 2 SSH项目 2.0 项目的前期部署 2.1 创建项目 2.2 前端的一些jsp 2.3 web.xml 2.4 实体类 ...
- 一篇文章了解保偏光纤原理、快慢轴、保偏拍长、消光比
什么是保偏(PM)光纤? 从理论上来说,光纤是圆芯的应该不会产生双折射,并且光纤的偏振态在传播过程中是不会改变的.然而,在实际中,常规光纤在生产过程中,会受到外力作用等原因,使光纤粗细不均匀或弯曲等, ...
- 如何优雅的在 vue 中使用 非响应式对象_一篇文章上手Vue3中新增的API
1. 初始化项目 // ① npm i -g @vue/cli // ② vue create my-project // ③ npm install @vue/composition-api -S/ ...
- [ATF]-MTK:一篇文章了解ATF原理
关键词: Non-cacheable,Cacheable, non-shareable,inner-shareable,outer-shareable, optee.ATF.TF-A.Trustzon ...
- 一篇文章理解vuex原理
vuex作用: 组件的通信成本很高,所以为了简化组件间通信(共享数据),vue提供了vuex插件.是基于flux思想实现的. flux 是由react团队提供的数据通信架构思想.解决网状通信的问题.实 ...
- 使用Docker快速部署Gitlab
目录 什么是Docker Linux安装Docker Win10安装Docker 使用Docker安装Gitlab 使用阿里的镜像加速 安装Gitlab镜像 运行gitlab镜像 配置Docker 提 ...
- c++ socket线程池原理_一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题...
编辑:业余草来源:https://www.xttblog.com/?p=4946 一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题. ThreadLocal 相信不 ...
最新文章
- Excel VBA两两个体距离矩阵转化为数据库格式
- mysql的还原_MySQL 还原
- centos 7 minimal connect: Network is unreachable和ifconfig command not found
- 由浅到深理解ROS(3)-命名空间
- linux登录指令 pgsql_命令行方式登录PostgreSQL
- ylbtech-LanguageSamples-Struct(结构)
- 未来已来?揭开量子计算机的神秘面纱
- bzoj 1681: [Usaco2005 Mar]Checking an Alibi 不在场的证明(BFS)
- 第三节: 串口通信(用CubeMX学习STM32)
- java线程视频教程_java线程视频教程
- 三年探索:一条自控、电信/科类学生的技术成长路线
- c语言输入abc求方程的根,编写程序,输入系数abc,计算任意二次方根的实根
- 运动想象EEG背景知识
- “京东红”托起“松石绿” 湖北十堰让世界发现中国珠宝之美
- redhat 7 手册
- Unity3D学习:飞碟游戏进化版
- 文化产业如何面对大数据时代
- 2020.7.25T2魔道研究(jz暑假训练day10)
- Citrix虚拟化技术之五XenServer6.2资源池配置
- 刚认识的,推荐赚钱能力超级硬核的美女、大佬的公众号!
热门文章
- A. Arithmetic Array
- 17位时间戳转换为Unix时间戳及转换工具,代码实现转换 WebKit/Chrome Timestamp Converter
- kindle paperwhite3 android,Kindle Paperwhite3入手20天感受
- 手机计算机数字游戏怎么玩,计算器游戏攻略
- 从突变到新抗原:肿瘤与免疫系统之间的一场豪赌!
- 通用AI元素识别在UI自动化测试的最佳实践
- android 设置打印级别
- C++解决猜大小问题
- HyperLynx(十六)PCI-E的设计与仿真
- JAVA删除pdf空白页_如何从iText中的PDF中删除空白页面