Docker 入门基础
Docker基本概念
1.什么是Docker?
Docker是一种更轻量化的方式,使用Docker不需要安装客户OS;
Docker镜像中只隔离并安装服务器运行所需的程序和库文件,与主机共享OS资源,大大减少了镜像的体积。
相对于虚拟机,Docker提供了专门创建并部署镜像的功能和镜像上传和下载(push/pull)的功能。
2.Docker镜像和容器
基础镜像概念:它是指仅Linux发行版userland中安装的文件,一般为Linux发行版本的名称;“Docker镜像”通常是指安装基础镜像所需的程序、库、源代码之后创建的一个文件。
userland:即用户空间;在linux中,用户区是GNU,应用程序驻留在用户区中,而Linux内核(和大多数驱动程序)驻留在内核空间中。
引用:https://www.linux.org/threads/gnu-userland.11066/
Docker镜像:
只将基础镜像中变化的部分创建为镜像,运行时将基础镜像与可变部分合并运行;
Docker“层”的概念:Docker不创建整个镜像,只针对变化的部分进行创建,然后继续引用父镜像;
上传和下载镜像是会同时上传/下载子镜像和父镜像,之后只传输内容有变化的镜像。
Docker容器:
Docker容器是处于运行状态的镜像,使用一个镜像可以创建多个容器;
镜像可以理解为可执行.exe文件,容器是进程;
已经运行的容器中,可以将更改的部分创建为镜像。
Dokcer Engine
Dokcer Engine是一个C/S架构的应用程序,主要包含:
常驻后台进程Dockerd
一个用来和Dockerd交互的REST API Server
命令行CLI接口,通过REST API进行交互
Docker 架构
Docker使用C/S架构,Docker客户端和Docker守护进程通信,Docker守护进程负责构建、运行和分发Docker容器;
Docker客户端和守护进程可以在同一个系统上运行,也可以将Docker客户端连接到远程Docker守护进程;Docker客户端和守护进程使用REST API通过UNIX套接字或者网络接口进行通信。
Docker daemon用来监听Docker API的请求和管理Docker对象,比如镜像、容器、网络等。
Docker Client是与Docker进行交互最主要的方法,比如可以通过docker run来运行一个容器,然后Docker Client会把命令发送给Docker Daemon。
Docker Registry用来存储Docker镜像的仓库;默认情况下,我们使用docker pull或者docker run命令,就会从docker镜像仓库中去拉取镜像,使用docker push命令,会将我们构建的镜像推送到对应的镜像仓库中。
Images镜像,只将基础镜像中变化的部分创建为镜像,运行时将基础镜像与可变部分合并运行。
Containers容器,容器是一个镜像的可运行的实例,使用Docker REST API或者CLI来操作容器;容器的实质是进程,但与直接在宿主机执行的实例进程不同,容器进程属于自己的独立命名空间。容器可以拥有自己的root文件系统、网络配置、进程空间、用户ID。容器内的经常是运行在一个隔离环境里,使用起来,就好像在一个独立于宿主机的系统下操作一样,使得容器封装的应用比直接在宿主机运行更安全。
Docker核心
Docker namespace
Linux内核2.4.19中开始陆续引用namespace概念。目的是将某个特定的全局系统资源通过抽象的方法使得namespace中的进程看起来拥有它们自己的隔离的全局系统资源实例。
命名空间是Linux内核强大的特性;每个容器都有自己的命名空间,运行在其中的应用都是独立操作系统中运行一样,命名空间保证了容器之间彼此互不影响。
Docker CGroups
Docker Namespace来隔离docker其运行环境,使得容器中的进程看起来就像在一个独立的环境中运行;但仅允许环境隔离不够,因为这些进程是可以不受限制的使用系统资源。
Docker CGroups的目的是为了防止进程占用太多的资源而影响到其他进程;另外,在系统资源耗尽时,Linux内核会触发OOM这会让一些被杀掉的进程无辜死掉;因此为了让容器中的进程更加可控,使用Docker CGroups来限制容器中的进程允许使用的系统资源。
Docker UnionFS
UnionFS可以把文件系统上的多个目录内容联合挂载到同一目录下,而目录的物理位置是分开的。
bootfs: 包含操作系统boot loader和kernel;用户不会修改这个文件系统,一旦启动成功后,整个Linux内核加载进内存,之后bootfs会被卸载,从而释放内存。
rootfs: 包含典型的目录结构(/dev,/bin/,/etc,/usr,/lib,/tmp等);Linux系统在启动时,rootfs首先会被挂载为只读,启动完成后被修改为读写模式。
Dockerfile:
FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]
联合文件系统对应的层次结构:
顶上两层,是Docker为Docker容器新建的内容,二这两层属于容器范畴,分别为docker的初始层init layer和可读可写层read-write layes。
init layer:
大多是初始化容器环境时,与容器相关的环境信息,如容器主机名、host信息等。
read-write layes:
docker容器内的进程只对可读可写层拥有写权限,对其他层的进程而言都是只读的。
Docker常用命令
镜像&容器命令
##查看docker容器版本
docker version
##查看docker容器信息
docker info
##查看docker容器帮助
docker --help
##列出本地images
docker images
##搜索仓库MySQL镜像
docker search mysql
##下载Redis官方最新镜像,相当于:docker pull redis:latest
docker pull redis
##下载仓库所有Redis镜像
##单个镜像删除,相当于:docker rmi redis:latest
docker rmi redis
##强制删除(针对基于镜像有运行的容器进程)
docker rmi -f redis
##多个镜像删除,不同镜像间以空格间隔
docker rmi -f redis tomcat nginx
##删除本地全部镜像
docker rmi -f $(docker images -q)
容器命令
## 查询容器
docker ps // 查询所有容器
docker ps -a // 查询正在运行的容器
## 进度容器
docker exec -it 容器id /bin/bash
## 基于镜像新建并启动容器, 启动多个运行多次, 注意端口重复, 多个容器可以组成集群
docker run -i -p 宿主机端口:容器端口 --name 容器名称 镜像的标识|镜像名称[:tag]
##启动一个或多个已经被停止的容器
docker start redis
##重启容器
docker stop $(docker ps -qa)
docker stop/start/restart 容器id
##top支持 ps 命令参数,格式:docker top [OPTIONS] CONTAINER [ps OPTIONS]
##列出redis容器中运行进程
docker top redis
##查看所有运行容器的进程信息
for i in `docker ps |grep Up|awk '{print $1}'`;do echo \ &&docker top $i; done
##查看redis容器日志,默认参数
docker logs redis
docker logs 容器id -f
##查看redis容器日志,参数:-f 跟踪日志输出;-t 显示时间戳;--tail 仅列出最新N条容器日志;
docker logs -f -t --tail=20 redis
##查看容器redis从2019年05月21日后的最新10条日志。
docker logs --since="2019-05-21" --tail=10 redis
netstat -tunlp 查看端口占用情况 kill 进程id 删除端口占用进程
容器信息查询命令
docker inspect {image Id or container id}
##获取镜像redis的元信息
docker inspect redis
##获取正在运行的容器redis的 IP
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis
镜像构建
制作基础镜像
- 下载centos7镜像
docker search centos
docker pull centos:7
docker images
- 下载linux版本jdk jdk1.8.0_77.tar.gz
- 编译Dockerfile
FROM centos:7 ##这里使用的镜像是上面下载的centos镜像
MAINTAINER root ##指定作者
RUN mkdir -p /data/DockerImage ##功能为运行指定的命令
WORKDIR /data/DockerImage ##设置工作目录
ADD resource/jdk-8u202-linux-i586.tar.gz /data/DockerImage ## 一个复制命令,把文件复制到景象中,采用相对路径
##设置环境变量
ENV JAVA_HOME /data/DockerImage/jdk1.8.0_77
ENV JRE_HOME /data/DockerImage/jdk1.8.0_77/jre
ENV PATH $JAVA_HOME/bin:$PATH
- 根据Docker file创建jdk镜像
docker build -t java:8 . -f docker_file/jdk8_dockerFile
构建服务镜像
- 编写dockerfile
FROM java:8
MAINTAINER root
RUN mkdir -p /data/DockerImage
WORKDIR /data/DockerImage
# 复制文件
ADD basic-info-api-1.0.0-SNAPSHOT.jar /data/DockerImage/app.jar
# 容器对外映射的端口, 这里可以不需要
EXPOSE 15000
# 执行
ENTRYPOINT ["java","-jar","/data/DockerImage/app.jar"]
- 基于docketfile和基础镜像构建docker镜像
docker build -t basic-info . -f docker_file/basic-info_dockerFile
容器之间的访问
启动时link需要访问的容器(可多个)
docker run -it -p 15000:15000 --name basic-info-service --link core-zk basic-info
如果连接失败
docker: Error response from daemon: Cannot link to /core-zk, as it does not belong to the default network.
- 执行如下命令查看改容器得Networks
docker inspect [需要link的容器名称或ID]
- 查看所有容器Networks信息
docker network ls
- 启动容器并 --link所需容器
docker run -it -p 15000:15000 --name basic-info-service --net core-docker_default --link core-zk basic-info
解释:命令中core-docker_default为我们所要Link容器的network,例如上图红框中标注的bridge
如果telnet失败
本地telnet容器服务
telnet localhost 15000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host
原因是构建的镜像对外端口是15000, 容器对宿主机映射的端口也是15000导致端口重复, 连接被重置, 修改容器运行命令即可
bash
docker run -d -it -p 15000:15003 --name basic-info-service --net core-docker_default --link core-zk basic-info