思考并回答以下问题:
熟悉Docker的使用
视频操作要点:
首先来操作一下Docker Engine。
(有了课前准备的基础)在这台机器上,Docker已经安装好了,我给你用docker version
和docker info
看一下它的信息。
docker version
显示的是Docker Engine20.10.12,系统是Linux,硬件架构是arm64,也就是AppleM1。
docker info
显示的是当前系统相关的信息,例如CPU、内存、容器数量、镜像数量、容器运行时、存储文件系统等等。这里存储用的文件系统是overlay2,Linux内核是5.13,操作系统是Ubuntu 22.04 Jammy Jelly fish,硬件是aarch64,两个CPU,内存4G。
现在我们用docker ps
看一下容器列表,应该是空的。
然后用docke rpull
拉取busybox镜像,再用docker images
看镜像列表。
使用docker run
启动busybox镜像,执行最简单的helloworld:1
docker run busybox echo hello world
然后再用docker ps -a
查看已经结束的容器列表,应该可以看到刚刚运行完毕的Busybox容器,可以用docker rm
再加上容器ID删除它。
镜像和容器
视频操作要点:
我们再来拉取另一个镜像,操作系统Alpine:1
docker pull alpine
然后用docker run
,加上it参数,运行它里面的shell:1
docker run -it alpine sh
这样就暂时离开当前的Ubuntu操作系统,进入了容器内部的Alpine系统,可以在里面执行任意的命令,比如cat/etc/os-release。
这个容器环境与外面是完全隔离的,进程、文件系统都独立,不过也有没有隔离的部分,比如时间和内核。
使用exit退出容器,然后在宿主机环境执行date
、uname -a
,你就可以看到它与容器里是一致的。
让我们再运行一个容器:1
docker run -d --rm nginx:alpine
在宿主机里用ps -ef | grep nginx
可以看到有3个Nginx进程,它们其实就是容器里的Nginx进程,用docker stop
停止后再用ps,就能发现它们已经消失了。
这就证明,容器其实就是操作系统里的进程,只是被容器运行环境加上了namespace、cgroup、chroot的限制,所以容器和普通进程在资源的使用方面是没有什么区别的,也因为没有虚拟机的成本,启动更迅速,资源利用率也就更高。
构建自己的镜像
视频操作要点:
现在让我们来尝试编写Dockerfile,构建一个自己的镜像。
这个Dockerfile先用arg指令定义了IMAGE_BASE、IMAGE_TAG两个变量,然后使用from指令指定了构建的基础镜像,把这两个变量结合起来就是nginx:1.21-alpine。
后面的两个env指令定义了PATH和DEBUG两个环境变量。arg指令定义的变量只能在构建镜像的时候使用,而env定义的变量则会在容器运行的时候以环境变量的形式出现,让进程运行时使用。
接下来是copy指令,它会把构建上下文里的./default.conf
拷贝到镜像的/etc/nginx/conf.d/
,注意copy指令不能使用绝对路径,必须是构建上下文的相对路径,而且Docker会把构建上下文里的所有文件打包传递给docker daemon,所有尽量只包含必要的文件。
run指令就是构建镜像时要执行的shell命令,可以是安装软件、创建目录、编译程序等等,这里只是简单地用echo命令生成了一个文本文件。
最后两条指令是expose和workdir,expose是声明容器对外服务的端口号,而workdir是容器的工作目录。
了解了Dockerfile的内容之后,我们就要用docker build
来构建镜像了,使用-t打上标签,再加上构建上下文路径,当前目录就用一个点号.:1
docker build -t ngx-app:1.0 .
构建完成,生成镜像文件,我们可以用docker run
从镜像启动容器,验证镜像里的文件是否正确生成:1
docker run -it --rm ngx-app:1.0 sh
然后我们还可以用docker save/load
命令把它导出成压缩包,方便保存和传输:1
2docker save ngx-app:1.0 -o ngx.tar
docker load -i ngx.tar
与外部系统互通的操作
视频操作要点:
接下来我们看看容器与外部系统互通的一些操作。
首先是docker cp
命令。让我们先启动一个Redis容器:1
docker run -d --rm redis
然后用echo
命令生成一个简单的文本文件:1
echo 'aaa' > a.txt
用docker ps
命令看看容器的ID,就可以使用docker cp
命令把这个文件拷贝进容器里了:1
docker cp a.txt 062:/tmp
使用docker exec
可以进入容器内部,查看文件是否已经正确拷贝:1
2docker exec -it 062 sh
ls /tmp
退出容器,我们再把这个文件改个名字,拷贝出来:1
docker cp 062:/tmp/a.txt ./b.txt
现在我们再看看用-v
参数直接挂载本地目录,把文件直接映射到容器内部:1
docker run -d --rm -v /tmp:/tmp redis
用docker exec
进入容器,查看一下容器内的“/tmp”目录,应该就可以看到文件与宿主机是完全一致的。1
docker exec -it b5a sh # <span style="color:#339AFF;">b5a是容器ID
-p参数是映射本机端口到容器端口,我们启动一个Nginx容器,把本机的80端口映射到容器的80端口:1
docker run -d -p 80:80 --rm nginx:alpine
dockerps可以看到端口的映射情况,我们也可以使用curl直接访问容器里的Nginx服务:1
curl 127.1:80 -I
再使用exec就可以看到容器里的网卡情况:1
docker exec xxx ip addr
可以发现容器里的网卡设置与宿主机完全不同,eth0是一个虚拟网卡,IP地址是B类私有地址“172.17.0.2”。
搭建WordPress
视频操作要点:
最后演示一下使用Docker搭建WordPress的过程。
因为在Docker命令里写环境变量很麻烦,命令很长,所以我把搭建的过程写成了一个脚本。
一共有三条命令,首先启动MariaDB,设置数据库名、用户名、密码等环境变量,然后启动WordPress,使用刚才的MariaDB的用户名、密码,db_host必须是MariaDB的IP地址,然后再启动Nginx,它需要在配置文件里指定WordPress的地址,然后用-v
参数挂载进容器里。
执行这个脚本之后,我们用docker ps
看一下容器的状态。
确认容器都运行正常,我们就可以在浏览器里输入IP地址,访问WordPress网站了。