Docker入门
一.Docker介绍及安装
Docker是容器技术的一个代表,容器技术从本质上讲是将程序隔离、打包的技术,不是一个很新的技术,核心的技术在内核里已经存在很久了,但这个技术真正被大家所用,变成这么流行、这么火爆的技术是因为Docker,Docker在2013年开源后发展的非常非常快。
Docker在云计算领域是一个非常火热的话题,Docker很好的理顺了开发和运维的环境的差异,使得开发和运维可以用同一个语言来沟通,另外,Docker和现在的deops、持续集成、持续交互、微服务等概念都是相辅相成的。
1.什么是Docker
Docker是一个开源的项目,它可以用来将任何应用以轻量级容器的形式来打包、发布和运行。在Node.js上是这样说Docker的:Docker允许一个应用程序及其所有依赖以一种标准的单位来打包。
类比:
可以粗糙地理解为轻量级的虚拟机
开挂的chroot
Docker确实不是虚拟机
Docker有一个Docker Engine层,在其上运行各种各样的程序,它是利用了Host OS里面的NameSpace、Control Group这些来做到将应用程序分离,因为它没有虚拟层这一个,会比虚拟机轻很多,程序启动速度、内存、存储需求都会小很多。
2.docker安装
a.mac安装
下载、安装、配置。
安装好后,可以执行docker info查看信息。
配置的话,由于docker官网很慢,可以在Registry mirrors中配置加速器,其实就是国内镜像。如阿里云、时速云等,去注册一个账号,就可以得到一个专属的加速器的地址,重启Docker即可。
b.Linux安装‘
$sudo wget -qO- https://get.docker.com | sh:安装Docker本身,wget是命令行的下载工具,它来下载https://get.docker.com这个地址,-q是让wget不要输出那么多,-O-意思是把wget的输出直接输出到标准输出(而不是输出到文件),然后用到管道的概念,把输出给后面的sh执行。这个命令会检测你的Linux的版本,根据你的版本用比较合适的安装包来安装,然后启一个服务。
$sudo usermod -aG docker imooc:修改用户的组,把imooc用户加到docker组,这样就允许非super user运行Docker,因为缺省安装后只允许root来执行。
c.Windows安装
二.Docker架构介绍与实践
中间是我们进行Docker操作的虚拟机,它运行了一个叫做Docker daemon的程序,这个程序负责做各种各样的Docker操作,比如下载镜像、运行一个容器,我们是通过Client用命令(如build、pull、run)交给Docker daemon,由Docker daemon来做实际的操作,右边是Registry,Docker daemon可以和它去交互,拖取一个image,或者push一个image,它是所有Docker玩家共享Docker镜像的服务。
这是一张中文版的架构图,客户端和守护进程进行操作,把命令送给守护进程,守护进程来拖取镜像、运行容器、并且和远端的镜像仓库进行交互。
用ubuntu这个image,在这里面运行了一个echo hello docker命令,输出就是hello docker。
docker run -p 8080:80 -d nginx命令返回一串字符串,这串字符串是Docker CONTAINER ID,-p是做端口映射的,是把Docker nginx本身的80端口映射到本地Host的8080端口,-d是允许这个程序直接返回,就是把这个容器做为守护进程来运行的。
docker ps可以看到当前正在运行的Docker容器,其中就是我们刚刚运行的CONTAINER ID 2b2eec668c76,同时还可以看到端口映射的关系,包括从什么image来的,运行什么样的命令等等,上面命令就是要本机的8080端口开启了一个nginx服务。
现在我在本地准备一个index.html文件,文件内容如下:
<html> <h1>Docker is fun!</h1> </html>
docker cp E:\develop\index.html b05d0bd5ecab:/usr/share/nginx/html
这样,Docker容器里面的一个网页已经被我们成功替换了。
docker stop 容器ID:停止Docker容器。
这时再用docker run -p 8080:80 -d nginx命令启动,再次访问localhost:8080,不再是“Docker is fun!”。因为Docker在容器内所做的改动都是暂时的,都缺省没有被保存下来的,而要保存需要做一些另外的操作。
docker commit命令保存了一个改动,实际上是产生了一个新的image。
docker rmi IMAGE ID:删除image。
docker stop 容器ID:停止正在运行的image。
docker ps:显示正在运行的容器
docker ps -a:列出所有的容器,包括运行过的,虽然我们把它停止了,但是它在系统里还是有一些历史,如希望把这些也去掉,用docker rm 容器ID。
命令小结:
docker pull:获取image
docker build:创建image
docker images:列出image
docker run:运行container
docker ps:列出container
docker rm:删除container
docker rmi:删除image
docker cp:在host和container之间拷贝文件
docker commit:保存改动为新的image
三.Dockerfile介绍
通过编写简单的文件自创docker镜像。
1.第一个Dockerfile
FROM alpine:latest MAINTAINER bijian CMD echo 'hello docker'
FROM alpine:latest:要产生的新镜像有一个Base image(基础镜像),alpine是一个专门针对Linux来做的一个极小的环境
MAINTAINER bijian:这个命令实际上是没有什么特别功效,在共享的时候告诉其他人这个是我写的而已
CMD echo 'hello docker':运行一个命令,这个就是我们最终运行容器要产生的效果
docker build -t hello_docker E:\develop\docker:新产生image。
-t:就是给它一个标签,标签就是hello_docker,最后给出一个路径名,实际上就是把这个路径下的所有内容都送给Docker Engine,让他来产生一个image。
2.dockerfile实战
Dockerfile
FROM ubuntu MAINTAINER bijian
RUN sed -i 's/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/mirrors.163.com\/ubuntu\//g' /etc/apt/sources.list RUN apt-get update RUN apt-get install -y nginx COPY E:\develop\docker\index.html /var/www/html entrypoint ["/usr/sbin/nginx","-g","daemon off;"] EXPOSE 80
FROM ubuntu:基础镜像ubuntu
RUN sed -i 's/http:\/\/archive.ubuntu.com\/ubuntu\//http:\/\/mirrors.163.com\/ubuntu\//g' /etc/apt/sources.list:做一个加速,用sed把/etc/apt/sources.list文件做一个改动,用的是国内的一个镜像,这样会比较快一些
RUN apt-get update:更新apt-get库
RUN apt-get install -y nginx:运行apt-get命令,安装nginx,-y参数表示不要问我(提醒我)
COPY E:\develop\docker\index.html /var/www/html:拷贝本地一个文件到容器里面去,不同版本ubuntu这个路径是不一样的
entrypoint ["/usr/sbin/nginx","-g","daemon off;"]:给出一个容器入点,这里是一个数组语法,三个字符串组成的数组,最后会把这个数组展开(用空格把它隔开),当成一个命令行来执行,作用是将nginx在前台执行
EXPOSE 80:暴露80端口,普通http服务的监听端口
E:\develop\docker\index.html内容是:今天是周末!
用docker build -t bj/hello-nginx E:\develop\docker命令构建时,一直未成功,如下所示:
将命令加上--no-cache,即创建镜像的过程不使用缓存后,docker build --no-cache -t bj/hello-nginx E:\develop\docker,都不成功。
用加速器:
不用加速器:
如果正常将会如下所示:
运行容器,命令:docker run -d -p 80:80 bj/hello-nginx,其中,-d:守护进程化,-p:把端口暴露出来。
Dockerfile语法小结:
FROM:base image
RUN:执行命令
ADD:添加文件,还可以将远程服务器上的文件加到容器上去
COPY:拷贝文件
CMD:执行命令,通常可用CMD和entrypoint给容器指定一个容器执行的入口
EXPOSE:暴露端口
WORKDIR:指定路径,指定我们运行命令的路径
MAINTAINER:维护者
ENV:设定环境变量
ENTRYPOINT:容器入口,和CMD相似都是设定容器入口,当然它和CMD又不一样,在没有指定entrypoint的时候,就用CMD来启动,如果指定了ENTRYPOINT,CMD所指定的字符串就变成了ENTRYPOINT的参数
USER:指定用户,即执行该命令的用户
VOLUME:mount point,指定容器所挂载的卷
3.镜像分层
Dockerfile中的第一行都产生一个新层。
每一行对应一个层,每一层有一个独立的ID,每一行的Dockerfile都产生一个新层。
已经存在image里面的层是可读的,一旦一个image被运行成一个容器的话,将会产生一个新层,这层叫做容器层,是可读可写的,这保证我们的容器是可以被改变的。
分层有什么好处呢?比如我有很多很多image,image A有10层,image B有7层,它们之间可能有5层是共享的,无形中我们的存储压力就小很多。
四.存储
1.volume介绍
提供独立于容器之外的持久化存储。之前我们看到我们在之前运行容器的时候,在容器中的改动,缺省是不会被保存的,Volume提供了一个方便的、可以持久化存储的技巧,比如我们运行一个数据库操作,数据库的容器,数据库真正的数据应该被持久化的,Volume就可以做这个事情,并且Volume可以提供容器与容器之间共享的数据。
2.volume操作
a.第一种形式的数据卷
$docker run -v /usr/share/nginx/html nginx:运行一个nginx容器,通过-v挂载一个卷。
docker inspect nginx命令来检查一下,它给出了容器很多很多的信息,我们关心如下信息:
它是把宿主机里的/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径挂载到容器内部的/usr/share/nginx/html地址。但是,在Windows上没有/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径,Mac上也是一样没有,在Mac上还有一层,它是通过一个虚拟层运行了一个主机,在这个主机里运行的Docker,在Mac上可以通过screen就可以进去。
如果用的是Linux Host的话,就没有这么复杂,直接进入/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径即可,而在Windows10上,我暂时也没有精力去研究它到底如何进的,暂时先不管,先知道就好了。
接着上面的,如果我们进入/var/lib/docker/volumes/61b1dcaa2a716cbd42383e9db3a425afd31f587e62cbdab12fc3a13a891b5f3f/_data路径下,就可以看到nginx的50x.html、index.html两个文件。echo "it's 2019" > index.html中去,回到Docker容器里面,就会发现内容被修改了。如下命令docker exec -it nginx /bin/bash可以进入容器。
b.第二种形式的数据卷
$docker run -v $PWD/code:/var/www/html nginx:本地的一个目录挂载到容器里面的数据卷里面去。
实例命令:docker run -p 80:80 -d -v E:\develop\docker\html:/usr/share/nginx/html nginx,表示将宿主机的E:\develop\docker\html目录挂载到/usr/share/nginx/html目录,但是我运行时还是不成功。
即便我参考https://blog.csdn.net/weixin_35723062/article/details/80989662进行了盘符共享,即进入Docker of windows的Setting 中进行配置,将盘符进行共享。
点击“Apply”并输入开机密码后依然好像没有共享成功的样子。如果运行成功,修改本机E:\develop\docker\html下的index.html内容,访问http://localhost将会看到修改后的内容。
其实这是一个很好的开发环境,我把本地开发的内容和容器内的服务器结合起来,无需到容器中去改,只需要在Host上改就可以自动的在容器内反应出来。
c.第三种形式的数据卷
$docker run --volumes-from ...:创建一个仅有数据的一个容器,并将这个容器当做Volume挂载到其它容器里面去。
但在我本机依然无法正常共享我本地的驱动。如下是学习视频的截图,是在Mac上安装Docker进行的操作。
上面的命令执行后,产生了一个仅有数据的一个容器,下面我们运行一个新的容器,把上面这个容器数据卷加载到新的容器里面去,--volumes-from表示从另外一个容器挂载,volumes-from data_container表示从上面的容器挂载。而我们要运行一个容器,所以也要给出一个镜像,在这里还是给出ubuntu,而ubuntu本身是一个基础镜像,它本身没有什么服务,所以-it用交互的方式来运行,这样我们会直接进入到我们的容器里面去。
进入容器后,我们执行mount命令,就可以看到挂载信息。
在容器里进入到/var/mydata目录,新建whatever.txt,退出容器,也可以看到刚在容器中新建的whatever.txt文件,这说明数据卷的挂载是成功。实际上,这个仅有数据的容器可以被多个容器挂载,做到数据共享。
五.镜像仓库
1.registry介绍
registry是镜像仓库,目的是为了大家来共享镜像。
a.术语
host:宿主机,就是我们正在使用的这台电脑。
image:镜像,是可以从远端拉取或者本地构建的、可以重复使用的软件的打包
container:容器,它是镜像的运行
registry:仓库
daemon:守护程序
client:客户端,给daemon输命令的,用来操作的
b.常用操作
$docker search whalesay:从Registry仓库里面搜索一个我想要的一个镜像
$docker pull whalesay:可以从Registry仓库把镜像pull下来
$docker push myname/whalesay:可以把我本地制作的镜像push到仓库去
c.国内的一些仓库
daocloud、时速云、aliyun
国内加速站点:
https://registry.docker-cn.com
http://hub-mirror.c.163.com
https://3laho3y3.mirror.aliyuncs.com
http://f1361db2.m.daocloud.io
http://141e5461.m.daocloud.io
特别说明:http://141e5461.m.daocloud.io搜索下载不成功,换成https://registry.docker-cn.com后OK。
2.registry实战
docker search whalesay,搜索到这么多结果,按STARS排序,OFFICIAL表明是否是官方的。
把镜像拖下来。
docker images,可以看到刚pull下来的whalesay镜像,REPOSITORY表示镜像名,TAG是标签,同一个镜像可以有很多TAG,比如1.0、2.0、3.0等等,latest是缺省的TAG。
运行docker/whalesay
docker tag docker/whalesay bijian/whalesay,制作新的镜像(虽然这里和原来的docker/whalesay是一样的,在这里仅为了演示而已)
docker push bijian/whalesay:把本地的镜像push到Docker仓库,push成功后,就可以在服务器上看到。
六.多容器app
1.compose介绍
通过docker-compose工具来拉起一个多容器的应用,在这里是编写一个简单的文本文件,这个文件描述一个多容器app的结构,然后通过docker-compose工具把它拉起来。
docker-compose安装:Mac/Windows自带,Linux:curl https://github.com/docker/compose...
2.compose-install-linux
Linux下安装:curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose,$(uname -s)就是把uname -s的命令的输出加在这个地方,形成一个完整的地址。
用curl -L下载下来,再用管道的方式写到/usr/local/bin/docker-compose文件中。/usr/local/bin通常在我们的路径里面,可以保证我们在任何地方都可以执行compose这个命令。
3.compose实战
大致三个容器
先创建相应目录和Dockerfile文件。
ghost目录下的Dockerfile文件内容如下:
FROM ghost COPY ./config.js /var/lib/ghost/config.js EXPOSE 2368 CMD ["npm", "start", "--production"]
config.js内容如下:
var path = require('path'), config; config = { production: { url: 'http://mytestblog.com', mail: {}, database: { client: 'mysql', connection: { host: 'db', user: 'ghost', password: 'ghost', database: 'ghost', port: '3306', charset: 'utf8' }, debug: false }, paths: { contentPath: path.join(process.env.GHOST_CONTENT, '/') }, server: { host: '0.0.0.0', port: '2368' } } }; module.exports = config;
进入到nginx目录,再创建Dockerfile文件,内容如下:
FROM nginx COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80
在此目录下新建nginx.conf内容如下:
worker_processes 4; events {worker_connections 1024;} http { server { listen 80; location / { proxy_pass http://ghost-app:2368; } } }
最后在nginx、ghost、data同级的目录下新建docker-compose.yml文件,内容如下:
version: '2' networks: ghost: services: ghost-app: build: ghost networks: - ghost depends_on: - db ports: - "2368:2368" nginx: build: nginx networks: - ghost depends_on: - ghost-app ports: - "80:80" db: image: "mysql:5.7.15" networks: - ghost environment: MYSQL_ROOT_PASSWORD: mysqlroot MYSQL_USER: ghost MYSQL_PASSWORD: ghost volumes: - ./data:/var/lib/mysql ports: - "3306:3306"
yml文件是yaml语法,它是现在比较常用的配置文件的格式,是通过缩进的方式来表达层级关系,比如这个文件有三个顶层的对象ghost-app、nginx、db对应上面的三个服务,每个服务有各自的描述,如ghost-app依赖db,有端口映射关系。
我们这里共创建了三个目录,ghost、nginx是用来存放Dockerfile和配置文件,用来构建镜像的,data本身是用来存放博客需要的数据,compose是用名字把各个服务联系起来,自已会把名字解析。
经过上面的准备工作,可以把整个系统拉起来,命令:docker-compose up -d。
可以用docker-compose stop把它停掉,docker-compose rm可以把停掉的各个容器删掉,如果有修改配置文件需要重新构建,命令:docker-compose build,再用docker-compose up -d命令拉起来。
最终还是没能正常启动,学习视频是正常启动运行的。
依次创建了db、ghost、nginx,表示已经起来了,在浏览器中输入http://localhost,显示如下:
输入localhost/ghost可以用来做配置,配置好后写一个博客,再进入http://localhost即可看到刚发布的博客。
docker-compose.yml常用命令:
build:本地创建镜像
command:覆盖缺省命令
depends_on:连接容器
ports:暴露端口
volumes:卷
image:pull镜像
docker-compose命令:
up:启动服务
stop:停止服务
rm:删除服务中的各个容器
logs:观察各个容器的日志
ps:列出服务相关的容器
七.小结
Docker介绍、如何制作镜像、如何分享镜像、如何持久化容器数据、如何编排一个多容器的应用
学习地址:https://www.imooc.com/learn/867
参考文章:https://blog.csdn.net/weixin_35723062/article/details/80989662、https://blog.csdn.net/ldzm_edu/article/details/78251528
posted on 2019-02-06 22:08 bijian1013 阅读(328) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架