Docker初探之基本使用篇

一、为什么要用Docker

  1. 容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker对系统资源的利用率更高,因此相比于传统的虚拟机技术,一个相同配置的主机能够运行更多数量的应用。
  2. Docker容器应用由于直接运行在宿主内核,无需启动完整的操作系统,因此有更快的启动时间
  3. Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境的一致性
  4. 实现一次创建或配置,可以在任意地方正常运行,使用Dockerfile使镜像构建透明化;
  5. Docker确保了执行环境的一致性,使得应用的迁移更容易
  6. Docker使用的分层存储以及镜像的技术,使得应用重复部分的服用更为容易,方便应用的维护和扩展

二、基本概念

镜像

Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会改变。

Linux的内核启动后,会挂载root文件系统为其提供用户空间支持,而Docker镜像就相当于一个root文件系统,比如官方镜像ubuntu:18.04就包含完整的一套Ubuntu18.04最小系统的root文件系统。

Docker设计时,充分利用Union FS技术,将镜像设计为分层存储的架构,所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

容器

容器和镜像的关系就像是面向对象程序设计中的对象与类的关系一样,镜像是静态的定义,容器是镜像运行时的实体。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。

每个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,可称这个为容器运行时读写而准备的存储层为容器存储层

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录],在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

仓库

Docker Registry是一个集中的存储、分发镜像的服务

一个Docker Registry包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

三、镜像加速

可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://knr0kbp8.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}

运行docker info命令即可看到相应的配置说明此时镜像加速成功。

image-20201011130819254

四、Docker常用命令

帮助命令

docker version        # 显示docker的版本信息
docker info           # 显示docker的系统信息,包括镜像和容器的数量
docker command --help # 帮助命令 

镜像命令

  • docker images
  • docker search
  • docker pull
  • docker rmi

docker images 查看所有本地的主机上的镜像:

root@ubuntu:/home/luo# docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               alpine              6f715d38cfe0        8 weeks ago         22.1MB
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB

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

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

docker search 搜索镜像:

image-20201011142244492

可选项:

--filter, -f  基于给定的条件对输出进行过滤
docker search --filter stars=3                    busybox 搜索stars数量大于3的镜像
docker search --filter is-automated=true busybox  搜索自动化镜像
docker search --filter is-official=true --filter stars=3 busybox  搜索官方镜像

docker pull 下载镜像:

# 下载镜像 docker pull 镜像名[:tag]
root@ubuntu:/home/luo# docker pull mysql
Using default tag: latest	# 如果不写tag,默认就是latest
latest: Pulling from library/mysql
d121f8d1c412: Pull complete # 分层下载,docker image的核心:联合文件系统
f3cebc0b4691: Pull complete 
1862755a0b37: Pull complete 
489b44f3dbb4: Pull complete 
690874f836db: Pull complete 
baa8be383ffb: Pull complete 
55356608b4ac: Pull complete 
dd35ceccb6eb: Pull complete 
429b35712b19: Pull complete 
162d8291095c: Pull complete 
5e500ef7181b: Pull complete 
af7528e958b6: Pull complete 
Digest: sha256:e1bfe11693ed2052cb3b4e5fa356c65381129e87e38551c6cd6ec532ebe0e808 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真实地址

# 二者等价
docker pull mysql
docker pull docker.io/library/mysql:latest

查看Docker Hub上mysql镜像拉取所支持的标签,进而指定标签拉取镜像。

image-20201011143350153

root@ubuntu:/home/luo# docker pull mysql:5.7
5.7: Pulling from library/mysql
d121f8d1c412: Already exists 
f3cebc0b4691: Already exists 
1862755a0b37: Already exists 
489b44f3dbb4: Already exists 
690874f836db: Already exists 
baa8be383ffb: Already exists 
55356608b4ac: Already exists 
277d8f888368: Pull complete 
21f2da6feb67: Pull complete 
2c98f818bcb9: Pull complete 
031b0a770162: Pull complete 
Digest: sha256:14fd47ec8724954b63d1a236d2299b8da25c9bbb8eacc739bb88038d82da4919
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 根据容器id删除镜像,-f选项用于强制删除镜像:

docker rmi -f 容器id		            # 删除指定的镜像
docker rmi -f 容器id 容器id 容器id     # 删除多个容器镜像
docker rmi -f $(docker images -aq)   # 删除全部的容器镜像 

容器命令

说明:有了镜像之后才可以创建容器,在这里我们通过centos镜像来测试学习。

  • docker run
  • docker ps
  • docker rm
  • docker start/stop/restart/kill

首先拉取centos镜像:

image-20201011144855775

docker run 新建容器并启动。

root@ubuntu:/home/luo# docker run --help
Usage:	docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 参数说明
--name="Name"		为容器指定名字,例如tomcat01、tomcat02来区分容器
--detach, -d		后台方式运行容器
-it					使用交互方式运行,进入容器查看内容
-p					指定容器端口, -p 8080:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口(常用)
	-p 容器端口
	容器端口
-P					随机指定端口

# 测试,启动并进入容器
root@ubuntu:/home/luo# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              0d120b6ccaa8        2 months ago        215MB
root@ubuntu:/home/luo# docker run -it centos /bin/bash
[root@4ea95e7ee45f /]# ls		# 查看容器内的centos,基础版本,许多命令并不完善
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
# 从容器中退出主机
[root@4ea95e7ee45f /]# exit
exit
root@ubuntu:/home/luo# ls
demo     Documents  examples.desktop  linux-4.15.tar.gz  node-bulletin-board  Public   Templates  xdp-tutorial
Desktop  Downloads  go                Music              Pictures             sockmap  Videos

退出容器使用exit命令是直接停止容器并退出,可使用快捷键ctrl+P+Q从而在容器不停止的情况下退出。

docker ps 列出所有运行的容器:

root@ubuntu:/home/luo# docker ps --help

Usage:	docker ps [OPTIONS]

List containers

# 不加任何选项默认只显示当前正运行的容器
Options:
  -a, --all             # 列出当前正在运行的容器和历史运行过的容器
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print containers using a Go template
  -n, --last int        # 显示最近创建的n个容器
  -q, --quiet           # 只显示容器的编号
# 运行效果
root@ubuntu:/home/luo# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@ubuntu:/home/luo# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS                NAMES
4ea95e7ee45f        centos              "/bin/bash"              14 minutes ago      Exited (0) 14 minutes ago                         zen_edison
704c4795b10c        centos              "/bin/bash"              20 minutes ago      Exited (13) 19 minutes ago 

docker rm 删除容器

docker rm 容器id			# 删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -f
docker rm -f $(docker ps -aq)	# 删除所有的容器
docker ps -aq|xargs docker rm   # 删除所有的容器

docker start/restart/stop/kill 启动 重启 停止 强制停止容器的操作

docker start 容器id		# 启动容器
docker restart 容器id		# 重启容器
docker stop 容器id 		# 停止当前正在运行的容器
docker kill 容器id 		# 强制停止当前容器

image-20201011153458284

常用其他命令

后台启动容器
# 命令 docker run -d 镜像名

image-20201011162031360

常见的坑:docker容器使用后台运行,就必须有一个前台进程,docker发现前台没有应用,就会自动停止。nginx容器启动后,发现自己没有提供服务,也会立刻停止。

查看日志
docker logs
# 选项
--follow, -f			# 跟踪容器日志的最新更新
--timestamps,-t			# 显示时间戳
--tail num(default all)	# 从日志尾部开始展示的日志的条数 

# 显示日志
# 通过shell脚本在centos bash中循环打印iie字符串
root@ubuntu:/home/luo# docker run -d centos /bin/sh -c "while true;do echo iie;sleep 1; done"
b449e7455e6e8cbcdf3ca8df661cfd6ac921465ff93296eb25097869ebbe3160
root@ubuntu:/home/luo# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b449e7455e6e        centos              "/bin/sh -c 'while t…"   4 seconds ago       Up 3 seconds                            angry_wozniak
root@ubuntu:/home/luo# docker logs -tf --tail 10 b449e7455e6e
2020-10-11T08:32:24.591396088Z iie
2020-10-11T08:32:25.593913720Z iie
2020-10-11T08:32:26.595235908Z iie
2020-10-11T08:32:27.600110698Z iie
2020-10-11T08:32:28.603608767Z iie
2020-10-11T08:32:29.607475099Z iie
2020-10-11T08:32:30.612909623Z iie
2020-10-11T08:32:31.615959954Z iie
2020-10-11T08:32:32.620009950Z iie
2020-10-11T08:32:33.623083108Z iie
2020-10-11T08:32:34.630690386Z iie
2020-10-11T08:32:35.633210432Z iie
查看容器中的进程信息
# 命令 docker top 容器id
root@ubuntu:/home/luo# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b449e7455e6e        centos              "/bin/sh -c 'while t…"   5 minutes ago       Up 5 minutes                            angry_wozniak
root@ubuntu:/home/luo# docker top b449e7455e6e 
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                100008              99984               0                   01:32               ?                   00:00:00            /bin/sh -c while true;do echo iie;sleep 1; done
root                100407              100008              0                   01:37               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像的元数据
docker inspect 容器id
进入当前正在运行的容器
# 通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
# 第一种命令
docker exec -it 容器id /bin/bash
# 测试
root@ubuntu:/home/luo# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b449e7455e6e        centos              "/bin/sh -c 'while t…"   16 minutes ago      Up 16 minutes                           angry_wozniak
root@ubuntu:/home/luo# docker exec -it b449e7455e6e /bin/bash
[root@b449e7455e6e /]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.1  11884  2880 ?        Ss   08:32   0:00 /bin/sh -c while true;do echo iie;sleep 1; done
root       1028  1.0  0.1  12016  3328 pts/0    Ss   08:49   0:00 /bin/bash
root       1042  0.0  0.0  23024  1284 ?        S    08:49   0:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /
root       1043  0.0  0.1  44592  3412 pts/0    R+   08:49   0:00 ps aux

# 第二种命令
docker attach 容器id
# 测试
root@ubuntu:/home/luo# docker attach b449e7455e6e
正在执行当前代码...

# docker exec		# 进入容器后开启一个新的终端
# docker attach		# 进入容器正在执行的终端,不会启动新的进程
容器内文件拷贝到主机目录

docker cp 容器id:源文件路径 主机目的文件路径

docker cp 容器id:源文件路径 目的文件路径
# 测试
root@ubuntu:/home/luo# docker exec -it b449e7455e6e /bin/bash
[root@b449e7455e6e /]# pwd
/
[root@b449e7455e6e /]# more main.go  # 查看文件中新建的go文件内容
package main

import "fmt"

func main(){
	fmt.Println("Hello World!")
}
[root@b449e7455e6e /]# exit
exit
root@ubuntu:/home/luo# docker cp b449e7455e6e:/main.go /home/luo
root@ubuntu:/home/luo# more main.go
package main

import "fmt"

func main(){
	fmt.Println("Hello World!")
}

一些实践

配置nginx
root@ubuntu:/home/luo# docker run -d --name nginx01 -p 8086:80 nginx
e8c4b4e392cce366505e7b3c63a7d3dabcccd37b4e9336ff0adb7f4de65e8dfd
root@ubuntu:/home/luo# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
e8c4b4e392cc        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:8086->80/tcp   nginx01
root@ubuntu:/home/luo# curl localhost:8086
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

在主机端访问主机ip以及8086端口也能够显示对应的html页面:

image-20201011171859449

当继续执行docker stop e8c4b4e392cc之后停止容器,此时再次刷新页面显示无法访问网站。

配置tomcat
# 拉取镜像
docker pull tomcat
# 运行容器
docker run -d -p 8888:8080 --name tomcat01 tomcat
# 测试访问没有问题
# 进入容器
docker exec -it tomcat01/ /bin/bash
# 发现问题:Linux命令少了,没有webapps(从webapps.dist拷贝过来);阿里云镜像默认是最小的镜像,保证最小可运行的环境,所有不必要的都会被剔除掉。

主机访问结果:

image-20201011174551887

commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]

image-20201011183821144

五、总结

通过上面的学习,基本上掌握了docker的基本用法,同时对镜像分层的原理所有理解,个人感觉刚上手一项技术的时候还是看视频快点,看书或者官方文档容易抓不住重点,在对技术有了初步地了解之后再去针对性地查阅书籍或者文档往往会事半功倍(小伙伴们可以分享一下自己的学习方式哟)。以上就是Docker的入门知识了,下篇博文将会分享关于Docker数据卷、Dockerfile以及容器网络的内容,敬请期待!

六、参考

Docker–从入门到实践

Docker官方文档

Dockerhub

B站Docker最新超详细版教程

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值