Docker学习笔记-理论篇
1、疑问和困惑
随着初步了解,有一些疑问和困惑,这些问题及回答的准确性,本人完全不能保证,只是一个小白学习和使用时产生的问题以及自己理解后的猜想。
1、单个docker类似一个linux虚拟机,那么集群时是不是要开多个docker,相当于开多个虚拟机?
经过多方查阅资料,docker并不是开多个操作系统。docker有image,这个image就相当于android的APK安装文件,运行时系统把APK拷贝到虚拟机生成一个实例,docker中把这个实例叫做 Container,每个Container之间几乎没有任何联系,相当于沙盒。这个image目前我理解的是,image可以被运行为多个实例(Container),会生成多个ID,但是需要配置一些文件防止冲突,比如命名空间、端口号、配置文件等等。
2、docker的image中有nginx、tomcat等镜像,他们是安装软件吗?他们和原生软件有什么关系?
关系示意图
他们不是原生软件,当用docker run
一个image后,用docker exec -it
指令进去用shell交互时,用ls
查看当前目录,发现这个image就是个独立的操作系统,拿nginx的image来说,这个image被运行起来后,整个操作系统基本上就运行了一个nginx的软件。所以完全可以同时运行多个nginx的image,因为他们之间是操作系统级别的隔离。但是docker的image被运行起来后,只是个进程(Container),不是虚拟机的整个系统。
简单粗暴的理解就是:虚拟机可以装多个软件和操作系统一样,docker的image就只装一个软件。
3、docker的image运行起来后(Container),如何在后台执行?
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。
4、docker运行数据库时,数据都存储在哪里,以<关系示意图>为例,是存储在"linux操作系统"这一层吗?
不是,docker的Container运行起来后,也可以存储数据,但是一旦停止或者被rm掉,数据就消失了,相当于是运行时数据。一般是通过挂载“云服务器”的硬盘数据来做存储,在容器中管理数据主要有两种方式:数据卷(Volumes)、挂载主机目录 (Bind mounts)
2、安装
docker分ce社区免费版和ee企业版,这里介绍的是免费版的安装,参考官方文档。
卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
安装工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
添加yum信息源
sudo yum-config-manager --add-repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
更新yum缓存
sudo yum makecache fast
安装 docker ce
sudo yum install docker-ce docker-ce-cli containerd.io
使用脚本自动安装
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun
启动docker
systemctl start docker
开机启动
systemctl enable docker
验证是否正确安装
docker run hello-world
添加内核参数
如果在 CentOS 使用 Docker CE 看到下面的这些警告信息:
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
添加内核配置参数以启用这些功能。
sudo tee -a /etc/sysctl.conf <<-EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF
然后重新加载 sysctl.conf
sudo sysctl -p
3、Dockerfile
创建Dockerfile文件
vim /home/server/Dockerfile
写入以下内容
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
FROM 指定基础镜像
RUN 执行命令行命令,多行操作用&&
连接,千万不要写多个RUN指令,正确写法如:
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html \
&& cd /root \
&& ls
进入Dockerfile所在目录构建新的nginx image
docker build -t nginx:v1 .
这个.
实际上是在指定上下文的目录, docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像,所以在Dockerfile脚本所在目录尽量不要放置其他无关内容,如果文件繁多,可以用.dockerignore
来忽略无关文件。
启动nginx,映射真实服务器端口的10001端口到docker的80端口
docker run --name nginx1 -d -p 10001:80 nginx:v1
3.1、Dockerfile指令详解
COPY
从当前构建文件夹下复制数据到image里。
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY package.json /usr/src/app/
通配符*,占位符?
COPY hom* /mydir/
COPY hom?.txt /mydir/
改变文件的所 属用户及所属组
COPY --chown=user1:mygroup files* /mydir/
ENV定义环境变量
ENV <key1>=<value1> <key2>=<value2>
ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
可以命名多个,后面用$VERSION
来引用,空格内容需要加双引号
ARG定义临时参数
ARG <参数名>[=<默认值>]
构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值。
VOLUME 定义匿名卷
VOLUME ["<路径1>", "<路径2>"...]
VOLUME /data
容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。
EXPOSE 声明端口
EXPOSE <端口1> [<端口2>...]
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。 -p ,是 映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访 问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行 端口映射。
HEALTHCHECK 健康检查
HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,我们可以用 curl 来帮助判断,其 Dockerfile 的 HEALTHCHECK 可以这么写:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib /apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit 1 作为健康检查命令。
查看运行状态
docker container ls
WORKDIR定义工作空间
相当于shell里的cd
,但是由于进程的问题,导致cd后和后续要执行的指令不在一个会话里
FROM node:slim
RUN mkdir /app
WORKDIR /app
COPY ./package.json /app
RUN [ "npm", "install" ]
COPY . /app/
CMD [ "npm", "start" ]
.dockerignore忽略文件
项目根目录下新建.dockerignore文件,用于忽略上传文件,和git忽略文件语法一致。
4、操作指令
docker run
用image启动Container
docker run --name web1 -d -p 8088:80 nginx
这条命令会用 nginx 镜像启动一个容器,命名为 web1,并且映射了真实物理机的 8088端口,这样我们可以用浏览器带8088端口去访问这个 nginx 服务器。
交互式终端方式进入web1
docker exec -it web1 bash
-t —— 分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
-i —— 让容器的标准输入保持打开
docker container
启动、停止、重启
docker container start
docker container stop
docker container restart
正在运行的容器信息
docker container ls
所有容器的信息包括已停止的
docker container ls -a
删除一个处于终止状态的容器
docker container rm web1
删除一个运行中的容器,可以添加 -f 参数
docker container rm -f web1
清理所有处于终止状态的容器
docker container prune
获取容器的输出信息
docker container logs [container ID or NAMES]
image
导出镜像
docker export 7691a814370e > ubuntu.tar
导入
cat ubuntu.tar | docker import - test/ubuntu:v1.0
从url导入
docker import http://example.com/exampleimage.tgz example/imagerepo
查找
docker search centos
下载
docker pull centos
上传
docker tag ubuntu:18.04 username/ubuntu:18.04
docker image ls
docker push username/ubuntu:18.04
docker search username
删除image
docker image rm web1
5、数据存储
数据卷(Volumes)
数据卷,类似于Linux下对目录或文件进行mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷。
创建一个名字叫my-vol的数据卷
docker volume create my-vol
查看所有的 数据卷
docker volume ls
查看指定数据卷
docker volume inspect my-vol
利用--mount来挂载数据到container里的/webapp目录下
docker run --name web1 -d -p 8088:80 nginx --mount source=my-vol,target=/webapp
删除数据卷
docker volume rm my-vol
清理无主的数据卷
docker volume prune
挂载主机目录 (Bind mounts)
docker run --name web1 -d -p 8088:80 nginx --mount type=bind,source=/src/webapp,target=/webapp
加载主机的 /src/webapp 目录到容器的 /webapp 目录
Docker 挂载主机目录的默认权限是 读写 ,用户也可以通过增加 readonly指定为只读
--mount type=bind,source=/src/webapp,target=/webapp,read only
挂载单个文件
--mount type=bind,source=/src/webapp/web.war,target=/webapp/web.war,read only
6、扩展
6.1 Docker Compose
使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker- compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目 (project)。
6.2 Docker Machine
在多种平台 上快速安装 Docker 环境,如果要给100台阿里云ECS安装上docker,传统方式就是你一台一台ssh上去安装,但是有了docker-machine,可以快速给100台ecs安装上docker。还有在本地快创建docker集群环境,总不能一台一台创建虚拟机吧,所以docker-machine可以解决这个问题。
6.3 Docker Swarm
Swarm 是使用 SwarmKit 构建的 Docker 引擎内置(原生)的集群管理和编排工具。如果在100台云服务器上安装了docker这时候难道要一个一个进如dokcer的客户端去管理,有了Swarm,你可以在一台叫做manager的节点上去管理集群。
6.4 Kubernetes
Kubernetes 是 Google 团队发起的开源项目,它的目标是管理跨多个主机的容器, 提供基本的部署,维护以及运用伸缩。功能应该是比Swarm要强大一些,但维护难度比Swarm要高一些,根据查阅的资料,如果是新手建议先搞懂Swarm,再来用k8s。