一文了解Docker的基本操作与使用

基本概念

Docker 包括三个基本概念:

  • 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
  • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。

docker

容器与镜像

镜像是一种静态的结构,可以看成面向对象里面的类,而容器是镜像的一个实例。

镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。

构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。

解决的问题

由于不同的机器有不同的操作系统,以及不同的库和组件,在将一个应用部署到多台机器上需要进行大量的环境配置操作。

Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 Docker 可以不修改应用程序代码,不需要开发人员学习特定环境下的技术,就能够将现有的应用程序部署在其它机器上。


Docker的优势

启动速度

启动虚拟机需要先启动虚拟机的操作系统,再启动应用,这个过程非常慢;

而启动 Docker 相当于启动宿主操作系统上的一个进程。

占用资源

虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU 资源,一台机器只能开启几十个的虚拟机。

而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。

更容易迁移

提供一致性的运行环境。已经打包好的应用可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。

更容易维护

使用分层技术和镜像,使得应用可以更容易复用重复的部分。复用程度越高,维护工作也越容易。

更容易扩展

可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。

安装

  • 环境查看
# 系统内核
[root@localhost /]# uname -r
3.10.0-1160.11.1.el7.x86_64
# 系统版本
[root@localhost /]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
  • 安装文档链接:https://docs.docker.com/engine/install/centos/
  1. 卸载旧的版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 安装需要的安装包(提供实用程序)
yum install -y yum-utils

# 若安装失败,可能是网络问题
# ping www.baidu.com失败,结果发现是(DNS文件没有配置)
#
#    vi /etc/resolv.conf 
#    nameserver 8.8.8.8
#    nameserver 8.8.4.4
  1. 设置镜像的仓库
# yum-config-manager \
#     --add-repo \
#     https://download.docker.com/linux/centos/docker-ce.repo		# 默认国外(慢)
    
# 使用阿里云镜像
yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  1. 安装最新版本的Docker 引擎和容器
# 可以先更新yum软件包索引
yum makecache fast

# 安装docker
yum install docker-ce docker-ce-cli containerd.io
  1. 启动docker
systemctl start docker

# 查看是否安装成功
docker version
  1. 测试:通过运行映像验证 Docker 引擎安装是否正确
docker run hello-world
  1. 查看下载的hello-world镜像
[root@localhost ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    bf756fb1ae65   13 months ago   13.3kB
  • 了解:卸载docker
# 卸载 Docker 引擎、CLI 和容器包
yum remove docker-ce docker-ce-cli containerd.io

# 删除资源
rm -rf /var/lib/docker

# /var/lib/docker         docker默认工作路径

常用命令

帮助命令
docker version		# 显示docker的版本信息
docker info			# 显示docker的系统信息(包括镜像和容器的数量)
docker --help		# 查看所有的命令
docker import --help	#查看目录的帮助

# 帮助文档:https://docs.docker.com/reference/
镜像命令
  • docker images:查看所有本地主机上的镜像
[root@localhost ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    bf756fb1ae65   13 months ago   13.3kB

-----------------------------------------------------------------
# 说明
REPOSITORY		# 镜像的仓库源
TAG				# 镜像的标签
IMAGE ID		# 镜像的id
CREATED			# 镜像创建的时间
SIZE			# 镜像的大小

# 可选项
Options:
  -a, --all             # 列出所有镜像
  -q, --quiet           # 只显示镜像id

--------------------------------------------------------------------
# 测试
[root@localhost ~]# docker images -a
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    bf756fb1ae65   13 months ago   13.3kB
[root@localhost ~]# docker images -q
bf756fb1ae65
  • docker search:搜索镜像
[root@localhost ~]# docker search mysql
..................列出在dockerhub搜索的结果(name,description,stars等).....................

-------------------------------------------------------------------------
# 可选项
Options:
  -f, --filter filter   过滤条件

-------------------------------------------------------------------------
# 测试
[root@localhost ~]# docker search mysql --filter=STARS=3000
..................搜索出来的镜像STARS数大于3000的.....................................
  • docker pull:下载镜像
# docker pull 镜像名[:tag]
[root@localhost ~]# docker pull mysql
Using default tag: latest		# 如果不写tag,默认就是latest最新版
latest: Pulling from library/mysql
45b42c59be33: Pull complete 	# 分层下载,docker image的核心,联合文件系统
b4f790bd91da: Pull complete 
325ae51788e9: Pull complete 
adcb9439d751: Pull complete 
174c7fe16c78: Pull complete 
698058ef136c: Pull complete 
4690143a669e: Pull complete 
f7599a246fd6: Pull complete 
35a55bf0c196: Pull complete 
790ac54f4c47: Pull complete 
18602acc97e1: Pull complete 
365caa3500d0: Pull complete 
Digest: sha256:b1cc887ed32cc6c2f217b12703bd05f503f2037892c8bb226047fe5dff85a109	# 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest		# 真实地址

------------------------------------------------------------------
# 指定版本下载
[root@localhost ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
45b42c59be33: Already exists    # 有与刚刚下载的mysql最新版重合的,故不用下载
b4f790bd91da: Already exists 	# 节省了内存(联合文件系统的优势) 
325ae51788e9: Already exists 
adcb9439d751: Already exists 
174c7fe16c78: Already exists 
698058ef136c: Already exists 
4690143a669e: Already exists 
66676c1ab9b3: Pull complete 
25ebf78a38b6: Pull complete 
349a839d5e27: Pull complete 
40b03e3e5980: Pull complete 
Digest: sha256:853105ad984a9fe87dd109be6756e1fbdba8b003b303d88ac0dda6b455f36556
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

-------------------------------------------------------------------
# 等价
docker pull mysql
docker pull docker.io/library/mysql:latest
  • docker rmi:删除镜像
# docker rmi -f 镜像id							删除指定镜像
# docker rmi -f 镜像id 镜像id 镜像id 镜像id			删除多个指定镜像
# docker rmi -f 镜像id $(docker images -aq)		删除全部镜像

---------------------------------------------------------------------------
# 测试
[root@localhost ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mysql         5.7       5f47254ca581   21 hours ago    449MB
mysql         latest    2933adc350f3   21 hours ago    546MB
hello-world   latest    bf756fb1ae65   13 months ago   13.3kB
[root@localhost ~]# docker rmi -f 5f47254ca581					# 删除指定
Untagged: mysql:5.7
Untagged: mysql@sha256:853105ad984a9fe87dd109be6756e1fbdba8b003b303d88ac0dda6b455f36556
Deleted: sha256:5f47254ca5817f99cdd387ce7345d43e770e0682a4c81b62776f3347551b1d85
......
[root@localhost ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mysql         latest    2933adc350f3   21 hours ago    546MB
hello-world   latest    bf756fb1ae65   13 months ago   13.3kB
[root@localhost ~]# docker rmi -f $(docker images -aq)			# 删除全部
Untagged: mysql:latest
Untagged: mysql@sha256:b1cc887ed32cc6c2f217b12703bd05f503f2037892c8bb226047fe5dff85a109
Deleted: sha256:2933adc350f3b62c05a66f700fba68ef93997d67263121250ec7848c50dcf3f5
......
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

容器命令
  • 说明:有了镜像才能创建容器
# 下载centos镜像来测试学习
docker pull centos
  • 新建容器并启动
docker run [可选参数] image

# 参数说明
--name="Name"	# 容器名字(用来区分容器)
-d				# 后台方式运行
-it 			# 交互方式运行(进入容器查看内容)
-p				# 指定容器端口		-p 主机端口:容器端口(常用)
									# 将容器中的某个端口映射到本地的某个端口上
-P				# 随机指定端口

-----------------------------------------------------------------------------
# 启动并进入容器
[root@localhost ~]# docker run -it centos /bin/bash
[root@83089d026ece /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# 从容器中退回主机
[root@83089d026ece /]# exit
exit
  • 退出容器
exit		# 退出并停止容器
Ctrl+P+Q	# 退出不停止容器
  • 列出所有运行的容器
docker ps		# 列出当前所有运行的容器
docker ps -a	# 列出当前所有运行的容器 + 过去运行的容器
docker ps -aq	# -q : 只显示容器编号
  • 删除容器
docker rm 容器id		# 删除指定容器(不能删除正在运行的容器)
docker rm -f 容器id	# 删除指定容器(可以强制删除正在运行的容器)
docker rm -f $(docker ps -aq)		# 删除所有容器
  • 启动和停止容器
docker start 容器id		# 启动容器
docker restart 容器id		# 重启容器
docker stop 容器id		# 停止当前正在运行的容器
docker kill 容器id		# 强制停止当前正在运行的容器

  • 问题
# 使用后台方式运行容器
docker run -d centos
# 但查看时发现容器没有运行
docker ps
# 原因:docker发现没有应用,会自动停止

  • 查看日志
docker logs -f -t 容器编号					# 显示所有日志	
docker logs -f -t --tail 条数 容器编号		# 显示指定条数日志

# 测试
[root@localhost ~]# docker logs -f -t --tail 10 ca683a40c363
  • 查看容器中的进程信息
docker top 容器id

[root@localhost ~]# docker top ca683a40c363
  • 查看镜像的元数据
docker inspect 容器id

  • 进入当前正在运行的容器
# 方式一 : docker exec -it 容器id /bin/bash
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND
ca683a40c363   centos    "/bin/bash"       
[root@localhost ~]# docker exec -it ca683a40c363 /bin/bash
[root@ca683a40c363 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@ca683a40c363 /]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 14:16 pts/0    00:00:00 /bin/bash
root         15      0  0 14:38 pts/1    00:00:00 /bin/bash
root         30     15  0 14:39 pts/1    00:00:00 ps -ef

# 方式二 : docker attach 容器id
[root@localhost ~]# docker attach ca683a40c363 
。。。。。。正在执行的代码。。。。。。

----------------------------------------------------------------------------

docker exec			# 进入容器后开启一个新的终端,可以在里面操作(常用)
docker attach		# 进入容器正在执行的终端,不会开启新的进程
  • 从容器内拷贝文件到主机
[root@localhost home]# docker attach ca683a40c363
[root@ca683a40c363 /]# cd /home
[root@ca683a40c363 home]# ls
[root@ca683a40c363 home]# touch first_test.java			# 新建文件
[root@ca683a40c363 home]# ls
first_test.java
[root@ca683a40c363 home]# exit  
exit		# 容器停止也没关系,只要存在就能拷贝
[root@localhost home]# docker cp ca683a40c363:/home/first_test.java /home
[root@localhost home]# ls
first_test.java
dockercmd

部署实战

部署nginx

1、搜索镜像(docker hub或使用docker search)

2、docker pull nginx

3、运行测试

# -d 后台运行  --name 给容器命名		-p 主机端口:容器端口
[root@localhost ~]# docker run -d --name nginx01 -p 3344:80 nginx
eb9f48472ee95a78b144180884e2207bf3ab37d55beae4564411ae66df036bdc
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  PORTS                  NAMES
eb9f48472ee9   nginx     "/docker-entrypoint.…"   0.0.0.0:3344->80/tcp   nginx01
[root@localhost ~]# curl localhost:3344

# 进入容器
[root@localhost ~]# docker exec -it nginx01 /bin/bash
root@eb9f48472ee9:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@eb9f48472ee9:/# cd /etc/nginx
root@eb9f48472ee9:/etc/nginx# ls
conf.d	fastcgi_params	koi-utf  koi-win  mime.types  modules  nginx.conf  scgi_params	uwsgi_params  win-utf

# 停止容器
root@eb9f48472ee9:/etc/nginx# exit
exit
[root@localhost ~]# docker stop nginx01				# stop 容器id或容器names
nginx01

部署tomcat
# 测试使用命令
docker run -it --rm tomcat:9.0
# docker run -it --rm  用完就删除容器(一般测试时使用)(删除后镜像还在)
# 一般使用
docker pull tomcat:9.0
docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0

# 测试访问时发现无法访问

# 发现问题
[root@localhost ~]# docker exec -it tomcat01 /bin/bash
root@4b6db47cca38:/usr/local/tomcat# ls
BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs	    temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin	      lib   native-jni-lib  webapps  work
root@4b6db47cca38:/usr/local/tomcat# cd webapps
root@4b6db47cca38:/usr/local/tomcat/webapps# ls
# webapps目录下为空(因为阿里云镜像只是保证最小可运行环境)
# 应用都放在webapps.dist目录下
root@4b6db47cca38:/usr/local/tomcat/webapps# cd ..
root@4b6db47cca38:/usr/local/tomcat# ls
BUILDING.txt	 LICENSE  README.md	 RUNNING.txt  conf  logs	    temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin	      lib   native-jni-lib  webapps  work
root@4b6db47cca38:/usr/local/tomcat# cd webapps.dist/
root@4b6db47cca38:/usr/local/tomcat/webapps.dist# ls
ROOT  docs  examples  host-manager  manager
# 进行拷贝
root@4b6db47cca38:/usr/local/tomcat# cp -r webapps.dist/* webapps

部署es
# es非常耗内存
docker run -d --name elasticsearch  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.1

# 查看cpu占用
docker stats 969c0b25f00e

# 修改配置
docker run -d --name elasticsearch01  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx256m"  elasticsearch:7.6.1

docker run -d --name elasticsearch  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx128m" -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins elasticsearch:7.6.1

# 访问
curl localhost:9200

docker可视化
  • 安装portainer(docker图形化界面管理工具)
docker run -d -p 9000:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

# 访问测试
http://192.168.132.3:9000

镜像原理

镜像:

镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件

联合文件系统

UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理:

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。

分层理解:

所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。

特点:

Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!


commit镜像
docker commit 提交容器成为一个新的副本
docker commit -m"提交的描述信息" -a"作者" 容器id 目标镜像名:tag
# 测试
1、启动一个默认的tomcat
2、发现没有webapps
3、进行拷贝
4、使用commit提交该修改过的镜像
# 类似于VM里的快照

docker_commit


容器数据卷

在Docker容器的实际使用中,经常会遇到容器的数据持久化,容器之间的数据共享等问题,通常我们有两种解决方案:

  • 1、数据卷(Data Volumes):就是将容器内数据直接映射到本地主机环境的指定文件目录之中,可以理解为容器挂载一个虚拟数据卷然后映射到一个主机目录中
  • 2、数据卷容器(Data Volume Containers):用专门的容器来挂载数据卷,其他容器通过挂载这个父容器来实现数据共享,这个专门挂载数据卷的容器就是数据卷容器,简单的总结就是有一个容器来专门管理数据的持久化和容器之间数据共享

前者常用于单一容器数据持久化,后者常用于多容器之间的数据共享和数据持久化


数据卷

方式一:直接使用命令来挂载 -v

docker run -it -v 主机目录:容器目录
# 测试
[root@localhost ~]# docker run -it -v /home/test:/home centos /bin/bash
# 可通过docker inspect 容器id 查看是否挂载

"Mounts": [
            {
                "Type": "bind",
                "Source": "/home/test",
                "Destination": "/home",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

实战MySQL
  • 解决MySQL数据持久化问题
-d 后台运行
-p 端口映射
-v 数据卷挂载
-e 环境配置
--name 容器名字
[root@localhost ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name my_mysql mysql:5.7

初始DockerFile

方式二:生成一个镜像时就进行挂载

[root@localhost docker-test-volume]# pwd
/home/docker-test-volume
# 编写dockerfile文件
[root@localhost docker-test-volume]# vim dockerfile1
[root@localhost docker-test-volume]# cat dockerfile1 
FROM centos

VOLUME ["volume1","volume2"]				# 匿名挂载

CMD echo "----end----"
CMD /bin/bash
# 构建镜像
[root@localhost docker-test-volume]# docker build -f dockerfile1 -t kim/centos .
Successfully built 684169834073
Successfully tagged kim/centos:latest
[root@localhost docker-test-volume]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
kim/centos            latest    684169834073   52 seconds ago      209MB
# 启动容器
[root@localhost docker-test-volume]# docker run -it 684169834073 /bin/bash
[root@2a70b06f1bdc /]# ls -l
total 0
lrwxrwxrwx   1 root root   7 Nov  3 15:22 bin -> usr/bin
drwxr-xr-x   5 root root 360 Feb 17 15:22 dev
drwxr-xr-x   1 root root  66 Feb 17 15:22 etc
drwxr-xr-x   2 root root   6 Nov  3 15:22 home
lrwxrwxrwx   1 root root   7 Nov  3 15:22 lib -> usr/lib
lrwxrwxrwx   1 root root   9 Nov  3 15:22 lib64 -> usr/lib64
drwx------   2 root root   6 Dec  4 17:37 lost+found
drwxr-xr-x   2 root root   6 Nov  3 15:22 media
drwxr-xr-x   2 root root   6 Nov  3 15:22 mnt
drwxr-xr-x   2 root root   6 Nov  3 15:22 opt
dr-xr-xr-x 115 root root   0 Feb 17 15:22 proc
dr-xr-x---   2 root root 162 Dec  4 17:37 root
drwxr-xr-x  11 root root 163 Dec  4 17:37 run
lrwxrwxrwx   1 root root   8 Nov  3 15:22 sbin -> usr/sbin
drwxr-xr-x   2 root root   6 Nov  3 15:22 srv
dr-xr-xr-x  13 root root   0 Feb 17 14:49 sys
drwxrwxrwt   7 root root 145 Dec  4 17:37 tmp
drwxr-xr-x  12 root root 144 Dec  4 17:37 usr
drwxr-xr-x  20 root root 262 Dec  4 17:37 var
drwxr-xr-x   2 root root   6 Feb 17 15:22 volume1		# 生成镜像时自动挂载(数据卷目录)
drwxr-xr-x   2 root root   6 Feb 17 15:22 volume2

# 查看外部同步的目录
# 使用docker inspect查看卷挂载的路径
"Mounts": [
            {
                "Type": "volume",
                "Name": "3d62dfe2c6f5da3091d52cc64f105c98e4196c1861d1544d9bac2be8a8391c30",
                "Source": "/var/lib/docker/volumes/3d62dfe2c6f5da3091d52cc64f105c98e4196c1861d1544d9bac2be8a8391c30/_data",			容器外的数据卷目录
                "Destination": "volume2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220",
                "Source": "/var/lib/docker/volumes/2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220/_data",			容器外的数据卷目录
                "Destination": "volume1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
            
[root@localhost _data]# cd /var/lib/docker/volumes/2e889d6623ada2313d0502f6e2a9d702a4995551994f42a37eefc12dee358220/_data
[root@localhost _data]# ls
container.txt

数据卷容器
  • 作用:实现容器间的数据共享

  • 应用:多个mysql同步数据

# docker01作为父容器
[root@localhost ~]# docker run -it --name docker01 kim/centos
[root@467f8f8d46af /]# ls -l
......
drwxr-xr-x   2 root root   6 Feb 18 01:49 volume1
drwxr-xr-x   2 root root   6 Feb 18 01:49 volume2
[root@localhost ~]# docker run -it --name docker02 --volumes-from docker01 kim/centos
[root@localhost ~]# docker run -it --name docker03 --volumes-from docker01 kim/centos

DockerFile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

Dockerfile
命令
FROM		# 基础镜像
MAINTAINER	# 维护者信息(姓名+邮箱)
COPY		# 复制指令,将文件拷贝到镜像中
ADD			# 添加内容
WORKDIR		# 镜像的工作目录
VOLUME		# 挂载目录
EXPOSE		# 暴露端口(与-p作用相同)
RUN			# 镜像构建时需要运行的命令
ENV			# 设置环境变量
CMD			# 指定容器启动时要运行的命令
# 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
# CMD 在 docker run 时运行
# RUN 是在 docker build
ENTRYPOINT	
# 类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖(即只有最后一个生效),而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序(即可追加命令)
ONBUILD		
# 在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

构建centos
  • 初始(无法使用vim、ifconfig等)
[root@localhost ~]# docker run -it centos
[root@0fda862a6d76 /]# vim
bash: vim: command not found
[root@0fda862a6d76 /]# ifconfig
bash: ifconfig: command not found
  • 添加内容
# 编写DockerFile的文件
[root@localhost dockerfile]# vim my_centos
[root@localhost dockerfile]# cat my_centos 
FROM centos
MAINTAINER KimTou<752160655@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH					# 默认的工作目录是/

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "------end------"
CMD /bin/bash

# 通过文件构建镜像
[root@localhost dockerfile]# docker build -f my_centos -t mycentos:1.0 .

# docker bild -f dockerfile文件路径 -t 镜像名:[tag] .

# 运行测试
[root@localhost dockerfile]# docker run -it mycentos:1.0
[root@3ee183346afd local]# pwd
/usr/local
[root@3ee183346afd local]# ifconfig

# 查看本地变更历史
docker history 镜像id

CMD与ENTRYPOINT
  • 测试CMD
# 编写dockerfile文件
[root@localhost dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls","-a"]
# 构建镜像
[root@localhost dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
Successfully built 23e5ab5b3d93
Successfully tagged cmdtest:latest
# run运行,发现 ls -a 命令生效
[root@localhost dockerfile]# docker run 23e5ab5b3d93
.
..
.dockerenv
bin
dev
etc
home
等等
# 此时追加一个命令"-l"(即为了形成ls -al),却报错
[root@localhost dockerfile]# docker run 23e5ab5b3d93 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

# 原因分析:CMD的情况下,-l替换了CMD ["ls","-a"]命令,而-l不是命令,所以报错

# 想正确执行,需使用
[root@localhost dockerfile]# docker run 23e5ab5b3d93 ls -al
  • 测试ENTRYPOINT
[root@localhost dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
[root@localhost dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint .
Successfully built fd019392b084
Successfully tagged entrypoint:latest
[root@localhost dockerfile]# docker run fd019392b084
.
..
.dockerenv
bin
dev
etc
home
等等

# 进行追加命令,直接拼接在ENTRYPOINT命令后面
[root@localhost dockerfile]# docker run fd019392b084 -l
total 0
drwxr-xr-x   1 root root   6 Feb 17 14:54 .
drwxr-xr-x   1 root root   6 Feb 17 14:54 ..
-rwxr-xr-x   1 root root   0 Feb 17 14:54 .dockerenv
lrwxrwxrwx   1 root root   7 Nov  3 15:22 bin -> usr/bin
drwxr-xr-x   5 root root 340 Feb 17 14:54 dev
drwxr-xr-x   1 root root  66 Feb 17 14:54 etc
drwxr-xr-x   2 root root   6 Nov  3 15:22 home
等等

制作tomcat镜像

1、准备镜像文件,tomcat压缩包、jdk压缩包

[root@localhost tomcat]# ls
apache-tomcat-9.0.38.tar.gz  jdk-8u281-linux-x64.tar.gz
[root@localhost tomcat]# pwd
/home/build/tomcat

2、编写dockerfile文件( 名字为Dockerfile,build就会自动寻找,不需要使用 -f 命令来指定)

FROM centos
MAINTAINER KimTou<752160655@qq.com>

COPY README.txt /usr/loacl/README.txt

ADD jdk-8u281-linux-x64.tar.gz /usr/local
ADD apache-tomcat-9.0.38.tar.gz /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8.0_281
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.38
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.38
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.38/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.38/bin/logs/catalina.out

3、构建镜像

[root@localhost tomcat]# docker build -t diytomcat .

4、启动镜像

[root@localhost tomcat]# docker run -d -p 8080:8080 --name diytomcat -v /home/build/tomcat/test:/usr/local/apache-tomcat-9.0.38/webapps/test -v /home/build/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.38/logs diytomcat 
b894eae2b2f0ad6650c1ef15c1079f83f80539acb9ce2fc15f1f5c8f48cfc930
[root@localhost tomcat]# docker exec -it b894eae2b2f0a /bin/bash

5、访问测试

curl localhost:8080				# 内部测试
http://192.168.132.3:8080/		# 外部测试

6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了)

[root@localhost tomcat]# ls
apache-tomcat-9.0.38.tar.gz  Dockerfile  jdk-8u281-linux-x64.tar.gz  README.txt  test  tomcatlogs
[root@localhost tomcat]# cd test
[root@localhost test]# ls
[root@localhost test]# pwd
/home/build/tomcat/test
[root@localhost test]# mkdir WEB-INF
[root@localhost test]# ls
WEB-INF
[root@localhost test]# cd WEB-INF/
[root@localhost WEB-INF]# vim web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

</web-app>
[root@localhost WEB-INF]# cd ..
[root@localhost test]# ls
WEB-INF
[root@localhost test]# vim index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello,我的tomcat</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("-----my test web logs-----");
%>
</body>
</html>

7、访问测试

http://192.168.132.3:8080/test/

发布镜像至DockerHub
  • 登录
[root@localhost tomcat]# docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username
[root@localhost tomcat]# docker login -u kimtou 
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
  • docker push
[root@localhost tomcat]# docker push diytomcat
Using default tag: latest
The push refers to repository [docker.io/library/diytomcat]
0b5f6503d033: Preparing 
1ca989e043c6: Preparing 
b0f9e083fd93: Preparing 
13ab4cbc0c90: Preparing 
2653d992f4ef: Preparing 
denied: requested access to the resource is denied		# 拒绝(原因:本地没有tag信息)
# 添加tag信息
[root@localhost tomcat]# docker tag a9181af1fc76(diytomcat镜像id) kimtou/tomcat:1.0
[root@localhost tomcat]# docker push kimtou/tomcat:1.0

Dokcer网络

理解docker0
# 查看内部网络地址
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo					# 本机回环地址
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:8b:8f:c6 brd ff:ff:ff:ff:ff:ff		# 虚拟机内网地址
    inet 192.168.132.3/24 brd 192.168.132.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::b337:5b2f:b8aa:54f7/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:40:82:c8:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0		# docker0地址
       valid_lft forever preferred_lft forever
  • 三个网卡
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat:9.0
e07dc049270c66313c2fa9d0bc3f59af5656012377ece17c887226fb68097716
# 查看容器的内部网络地址(不想进去/bin/bash,,只想查看网络地址,所以直接可以写ip addr)
[root@localhost ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
# 发现得到一个 eth0@if5 ip地址(docker分配的)

# 发现linux可以ping通容器内部
[root@localhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.295 ms
  • 启动容器后,再次使用ip addr
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:8b:8f:c6 brd ff:ff:ff:ff:ff:ff
    inet 192.168.132.3/24 brd 192.168.132.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::b337:5b2f:b8aa:54f7/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:40:82:c8:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:40ff:fe82:c842/64 scope link 
       valid_lft forever preferred_lft forever
5: veth2d24b84@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 26:e5:f5:40:f9:dc brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::24e5:f5ff:fe40:f9dc/64 scope link 
       valid_lft forever preferred_lft forever
# 多了 5: veth2d24b84@if4 ,这个正好对应容器的 4: eth0@if5
  • 启动另一个容器ping容器,发现可以ping通
[root@localhost ~]# docker run -d -P --name tomcat02 tomcat:9.0
db1d55c1d4888f7d91fe08acd742b149080982f221c7273c1c258fc8564e4add
[root@localhost ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.132 ms

自定义网络
  • 查看所有docker网络
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
86c387d828ca   bridge    bridge    local
804bff49826a   host      host      local
6525353ed74f   none      null      local

网络模式

  • bridge : 桥接模式(默认)
  • none : 不配置网络
  • host : 与宿主机(Linux服务器)共享网络
# 两者作用相同,使用docker0
docker run -d -P --name tomcat01 tomcat:9.0
docker run -d -P --name tomcat01 --net bridge tomcat:9.0
  • 创建自定义网络
# --driver bridge
# --subnet 192.168.0.0/16		192.168.0.2 ~ 192.168.255.255
# --gateway 192.168.0.1
# 创建自定义网络
[root@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
5e6793046451757d49b52b93be2d655dce9673b1b4abb72918de92b716d26654
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
86c387d828ca   bridge    bridge    local
804bff49826a   host      host      local
5e6793046451   mynet     bridge    local
6525353ed74f   none      null      local
  • 使用我们的自定义网络
# 启动两个容器
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat:9.0
df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat:9.0
7b73264240aec380c1ab3deb7e6d3bf773570065a8c68216b348db7afa617745
[root@localhost ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "5e6793046451757d49b52b93be2d655dce9673b1b4abb72918de92b716d26654",
        "Created": "2021-02-19T12:26:58.440470651+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "7b73264240aec380c1ab3deb7e6d3bf773570065a8c68216b348db7afa617745": {
                "Name": "tomcat-net-02",
                "EndpointID": "9136cf64444aeb45fbb7809d884fcf05b84e8d2d07a89cf588b5df9e70f986dc",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",		分配的ip地址
                "IPv6Address": ""
            },
            "df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3": {
                "Name": "tomcat-net-01",
                "EndpointID": "b8ff576a005ea18db3da7661e2e2fb65547bf4a61948bc54a3c7e74a163d0877",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",		 分配的ip地址
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
  • 用处
# 自定义网络可以使用域名ping通,则默认的docker0不行
[root@localhost ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.159 ms
[root@localhost ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.077 ms
  • 同时也可以让不同的集群使用不同的网络,如redis集群使用192.160.0.0,mysql集群使用192.161.0.0

网络连通
  • 尝试ping不同网段的容器(结果:无法ping)
[root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
  • 打通docker0与mynet
[root@localhost ~]# docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network		# 连接一个容器到一个网络
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
  • 测试打通 tomcat01 到 mynet
# 作用:将 tomcat01 放到 mynet 网络下(一个容器两个ip)
[root@localhost ~]# docker network connect mynet tomcat01
# 查看mynet发现tomcat01已被加入
[root@localhost ~]# docker network inspect mynet
"Containers": {
           "69e094144858a922928b9297bd5e59c2f04914f3138e0e31e9e5623daa594792": {
               "Name": "tomcat01",			加入mynet
               "EndpointID": "f4d4b6d389f7ceb223b60a41a8f751c283e8b0548c3a66dde632e7ccb89a11d0",
               "MacAddress": "02:42:c0:a8:00:03",
               "IPv4Address": "192.168.0.3/16",
               "IPv6Address": ""
           },
           "df65ecd0612fc3e4c1e1337c4f58d0d49c0289ced365e89b3cf1a8b0bfb87be3": {
               "Name": "tomcat-net-01",
               "EndpointID": "9247cf33ad07415038294d98de0875699ab0a4cd7d8c6099493eb4fdb4fd8230",
               "MacAddress": "02:42:c0:a8:00:02",
               "IPv4Address": "192.168.0.2/16",
               "IPv6Address": ""
           }
       },

SpringBoot微服务打包Docker镜像

1、创建SpringBoot项目

2、打包应用

3、编写dockerfile

FROM java:8

COPY *.jar app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]

4、构建镜像

[root@localhost idea]# ls
docker-0.0.1-SNAPSHOT.jar  Dockerfile
[root@localhost idea]# docker build -t kim-springboot .

5、发布运行

[root@localhost idea]# docker run -d -P --name kim-springboot-web kim-springboot
4a0ac515eaac0100dc69c5ecc9b10562bc71c45902ac4f4aa79516a9ddb3d264
[root@localhost idea]# docker ps
CONTAINER ID   IMAGE            COMMAND                  PORTS                     NAMES
4a0ac515eaac   kim-springboot   "java -jar app.jar -…"   0.0.0.0:49162->8080/tcp   kim-springboot-web
[root@localhost idea]# curl localhost:49162
{"timestamp":"2021-02-19T09:34:58.322+00:00","status":404,"error":"Not Found","message":"","path":"/"}[root@localhost idea]# curl localhost:49162/hello
hello,kim[root@localhost idea]# 

安装Vim

当我们进入docker容器时,经常会发现容器内并没有安装vim,此时需要我们手动去进行安装。

1、apt-get update

2、apt-get install vim

3、cd /usr/share/vim/vim81

4、vim defaults.vim

# 在=前加-
if has('mouse')
set mouse-=a
endif

文章内容参考狂神说:https://www.bilibili.com/video/BV1og4y1q7M4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值