当前位置: 首页 > news >正文

docker学习-入门篇

docker
1、基础命令
安装 sudo apt install -y docker.io #安装Docker Engine
启动 sudo service docker start #启动docker服务
将当前用户加入docker组否则报没有权限操作docker sudo usermod -aG docker ${USER} #当前用户加入docker组
docker version 会输出 Docker 客户端和服务器各自的版本信息
docker info 会显示当前 Docker 系统相关的信息,例如 CPU、内存、容器数量、镜像数量、容器运行时、存储文件系统等等
docker ps,它会列出当前系统里运行的容器,就像我们在 Linux 系统里使用 ps 命令列出运行的进程一样。
docker pull 拉取镜像类似ubantu的apt,注意拉取的是镜像image
docker images可以查看容器中的镜像
docker run 运行镜像
docker ps -a 可以查看到所有运行过的镜像,不加-a只能看到正在运行的镜像。其中的NAMES表示容器名称可以启动时候–name 指定,否则随机生成,两外PORTS可以看端口信息包括虚拟机与容器的端口映射关系
docker rmi 可以删除镜像后面加镜像的名字或者id如果名字后面不加版本号默认删除latest
docker run 是一个相对比较复杂的命令,详解
-it 表示开启一个交互式操作的 Shell,这样可以直接进入容器内部,就好像是登录虚拟机一样。(它实际上是“-i”和“-t”两个参数的组合形式)
-d 表示让容器在后台运行,这在我们启动 Nginx、Redis 等服务器程序的时候非常有用。
–name 可以为容器起一个名字,方便我们查看,不过它不是必须的,如果不用这个参数,Docker 会分配一个随机的名字。
–rm 参数,由于镜像与容器单独存在,如果不想每次再单独清理一遍容器,可以再启动的时候加上此参数,这样容器停止后就会自动删除
-v docker run 命令启动容器的时候使用 -v 参数就可以实现本机与容器内部目录共享,具体的格式是“宿主机路径: docker run -d --rm -v /tmp:/tmp redis 。-v 参数挂载宿主机目录的这个功能,对于我们日常开发测试工作来说非常有用,比如我本机上只有 Python 2.7,但我想用 Python 3 开发,如果同时安装 Python 2 和 Python 3 很容易就会把系统搞乱,所以我就可以这么做:先使用 docker pull 拉取一个 Python 3 的镜像,因为它打包了完整的运行环境,运行时有隔离,所以不会对现有系统的 Python 2.7 产生任何影响。在本地的某个目录编写 Python 代码,然后用 -v 参数让容器共享这个目录。现在就可以在容器里以 Python 3 来安装各种包,再运行脚本做开发了。先 docker pull python:alpine 再 docker run -it --rm -v pwd:/tmp python:alpine sh 非常适合有频繁修改的开发测试工作。
-p 用 : 分隔本机端口和容器端口 docker run -d -p 80:80 --rm nginx:alpine docker run -d -p 8080:80 --rm nginx:alpine
-env 运行的时候指定环境变量
样例:
docker run -d nginx:alpine # 后台运行Nginx
docker run -d --name red_srv redis # 后台运行Redis
docker run -it --name ubuntu 2e6 sh # 使用IMAGE ID,登录Ubuntu18.04
docker run -it alpine sh 启动命令加上-it启动后进入容器内部系统
docker run -d --rm nginx:alpine
docker exec 命令在里面执行另一个程序,效果和 docker run 很类似,但因为容器已经存在,所以不会创建新的容器。它最常见的用法是使用 -it 参数打开一个 Shell,从而进入容器内部 docker exec -it red_srv sh
docker stop 命令来强制停止,这里我们仍然可以使用容器名字,不过或许用“CONTAINER ID”的前三位数字会更加方便。docker stop ed4 d60 45c
docker start 停止运行的容器可以用 docker start 再次启动运行,
docker rm 如果你确定不再需要它们,可以使用 命令来彻底删除。这个只删除容器不删除镜像,被删除后使用docker ps -a 也看不到了就
docker inspect 来查看镜像的分层信息,比如 nginx:alpine 镜像 docker inspect nginx:alpine
docker save 可以把镜像导出成压缩包 docker save ngx-app:latest -o ngx.tar
docker load 从压缩包导入 Docker docker load -i ngx.tar 需要注意的是,save load 这两个命令默认使用标准流作为输入输出(为了方便 Linux 管道操作),所以一般会用 -o、-i 参数来使用文件的形式
docker cp 的用法很简单,很类似 Linux 的“cp”“scp”,指定源路径(src path)和目标路径(dest path)就可以了。如果源路径是宿主机那么就是把文件拷贝进容器,如果源路径是容器那么就是把文件拷贝出容器,注意需要用容器名或者容器 ID 来指明是哪个容器的路径。 docker cp a.txt 062:/tmp 这个062是容器id 使用docker exec -it 062 sh查看可以看到 反之docker cp a.txt 062:/tmp 拷贝出来
docker tag 拷贝并修改标签名 docker tag nginx:alpine 127.0.0.1:5000/nginx:alpine,以最后一个:分割名字与tag
docker logs 查看容器运行日志

2、容器本质
虚拟机与容器区别:从实现的角度来看,虚拟机虚拟化出来的是硬件,需要在上面再安装一个操作系统后才能够运行应用程序,而硬件虚拟化和操作系统都比较“重”,会消耗大量的CPU、内存、硬盘等系统资源,但这些消耗其实并没有带来什么价值,属于“重复劳动”和“无用功”,不过好处就是隔离程度非常高,每个虚拟机之间可以做到完全无干扰。我们再来看容器(即图中的Docker),它直接利用了下层的计算机硬件和操作系统,因为比虚拟机少了一层,所以自然就会节约CPU和内存,显得非常轻量级,能够更高效地利用硬件资源。不过,因为多个容器共用操作系统内核,应用程序的隔离程度就没有虚拟机那么高了。运行效率方面,由于不需要支撑多个操作系统减少大量CPU以及内存的占用,同样的资源容器运行效率就会高很多。一个普通的Ubuntu虚拟机安装完成之后,体积都是GB级别的,再安装一些应用很容易就会上到10GB,启动的时间通常需要几分钟,我们的电脑上同时运行十来个虚拟机可能就是极限了。而一个Ubuntu镜像大小则只有几十MB,启动起来更是非常快,基本上不超过一秒钟,同时跑上百个容器也毫无问题。不过,虚拟机和容器这两种技术也不是互相排斥的,它们完全可以结合起来使用,就像我们的课程里一样,用虚拟机实现与宿主机的强隔离,然后在虚拟机里使用 Docker 容器来快速运行应用程序。
容器隔离实现的三大基础:linux为资源隔离提供了三种隔离技术:namesapce2002年出现,它可以创建出独立的文件系统、主机名、进程号、网络等资源空间;cgroup2008年出现全程linuxcontrolgroup实现了对进程的CPU、内存等资源的优先级和配额限制;chroot 1979年就出现了,它可以更改进程的根目录也就是限制访问文件系统
容器就是被隔离的进程。镜像和常见的tar、rpm、deb等安装包一样,都打包了应用程序,但最大的不同点在于它里面不仅有基本的可执行文件,还有应用运行时的整个系统环境。这就让镜像具有了非常好的跨平台便携性和兼容性,能够让开发者在一个系统上开发(例如 Ubuntu),然后打包成镜像,再去另一个系统上运行(例如 CentOS),完全不需要考虑环境依赖的问题,是一种更高级的应用打包方式。

镜像的完整名字由两个部分组成,名字和标签,中间用:连接起来,而image_id才是镜像唯一编号,两个不同名字的镜像id可能一致,比如docker pull nginx:1.21-alpine docker pull nginx:alpine两者的image_id是一致的。image_id采用16进制表示本地 操作的时候不用像镜像名字那样写全可以通常写出前三位就基本唯一了,甚至一位两位都可以。比如docker  rmi redis 或者干脆 dockers rmi d4c一样	

3、制作自己的镜像-dockerfile

镜像本质:就是一个打包文件,里面包含了应用程序还有它运行所依赖的环境,例如文件系统、环境变量、配置参数等等。环境变量、配置参数这些东西还是比较简单的,随便用一个 manifest清单就可以管理,真正麻烦的是文件系统。为了保证容器运行环境的一致性,镜像必须把应用程序所在操作系统的根目录,也就是 rootfs,都包含进来。虽然这些文件里不包含系统内核(因为容器共享了宿主机的内核),但如果每个镜像都重复做这样的打包操作,仍然会导致大量的冗余。可以想象,如果有一千个镜像,都基于 Ubuntu 系统打包,那么这些镜像里就会重复一千次 Ubuntu 根目录,对磁盘存储、网络传输都是很大的浪费。很自然的,我们就会想到,应该把重复的部分抽取出来,只存放一份 Ubuntu 根目录文件,然后让这一千个镜像以某种方式共享这部分数据。这个思路,也正是容器镜像的一个重大创新点:分层,术语叫“Layer”。容器镜像内部并不是一个平坦的结构,而是由许多的镜像层组成的,每层都是只读不可修改的一组文件,相同的层可以在镜像之间共享,然后多个层像搭积木一样堆叠起来,再使用一种叫“Union FS 联合文件系统”的技术把它们合并在一起,就形成了容器最终看到的文件系统。但如果某两层的同一个位置都有干果,也就是有文件同名,那么我们就只能看到上层的文件,而下层的就被屏蔽了。nginx:alpine 镜像里一共有 6 个 Layer。相信你现在也就明白,之前在使用 docker pull、docker rmi 等命令操作镜像的时候,那些“奇怪”的输出信息是什么了,其实就是镜像里的各个 Layer。Docker 会检查是否有重复的层,如果本地已经存在就不会重复下载,如果层被其他镜像共享就不会删除,这样就可以节约磁盘和网络成本。

一、步骤一:dockerfile讲解-简单样例如下
FROM,所有的 Dockerfile 都要从它开始,表示选择构建使用的基础镜像,相当于“打地基”,这里我们使用的是 busybox。  FROM busybox

CMD,它指定 docker run 启动容器时默认运行的命令,这里我们使用了 echo 命令,输出“hello world”字符串。  CMD echo "hello world"

COPY,它的用法和 Linux 的 cp 差不多,不过拷贝的源文件必须是“构建上下文”路径里的,不能随意指定文件。也就是说,如果要从本机向镜像拷贝文件,就必须把这些文件放到一个专门的目录,然后在 docker build 里指定“构建上下文”到这个目录才行。

RUN, Dockerfile 里最重要的一个指令 RUN ,它可以执行任意的 Shell 命令,比如更新系统、安装应用、下载文件、创建目录、编译程序等等,实现任意的镜像构建步骤,非常灵活。RUN 通常会是 Dockerfile 里最复杂的指令,会包含很多的 Shell 命令,但 Dockerfile 里一条指令只能是一行,所以有的 RUN 指令会在每行的末尾使用续行符 \,命令之间也会用 && 来连接,这样保证在逻辑上是一行,就像下面这样:
RUN apt-get update \
	&& apt-get install -y \
		build-essential \
		curl \
		make \
		unzip \
	&& cd /tmp \
	&& curl -fSL xxx.tar.gz -o xxx.tar.gz\
	&& tar xzf xxx.tar.gz \
	&& cd xxx \
	&& ./config \
	&& make \
	&& make clean
有的时候在 Dockerfile 里写这种超长的 RUN 指令很不美观,而且一旦写错了,每次调试都要重新构建也很麻烦,所以你可以采用一种变通的技巧:把这些 Shell 命令集中到一个脚本文件里,用 COPY 命令拷贝进去再用 RUN 来执行:
COPY setup.sh  /tmp/                # 拷贝脚本到/tmp目录
RUN cd /tmp && chmod +x setup.sh \  # 添加执行权限
	&& ./setup.sh && rm setup.sh    # 运行脚本然后再删除
	
ARG和ENV, RUN 指令实际上就是 Shell 编程,如果你对它有所了解,就应该知道它有变量的概念,可以实现参数化运行,这在 Dockerfile 里也可以做到,需要使用两个指令 ARG 和 ENV。它们区别在于 ARG 创建的变量只在镜像构建过程中可见,容器运行时不可见,而 ENV 创建的变量不仅能够在构建镜像的过程中使用,在容器运行时也能够以环境变量的形式被应用程序使用。

EXPOSE,它用来声明容器对外服务的端口号,对现在基于 Node.js、Tomcat、Nginx、Go 等开发的微服务系统来说非常有用,例如
EXPOSE 443           # 默认是tcp协议
EXPOSE 53/udp        # 可以指定udp协议

创建镜像需要编写 Dockerfile,写清楚创建镜像的步骤,每个指令都会生成一个 Layer

dockerfile比较完成样例:
# Dockerfile
# docker build -t ngx-app .
# docker build -t ngx-app:1.0 .

ARG IMAGE_BASE="nginx"
ARG IMAGE_TAG="1.21-alpine"

FROM ${IMAGE_BASE}:${IMAGE_TAG}

COPY ./default.conf /etc/nginx/conf.d/  并且这个还只能是上下文的相对路径不能是绝对路径

RUN cd /usr/share/nginx/html \
	&& echo "hello nginx" > a.txt

EXPOSE 8081 8082 8083

WORKDIR 是容器运行的工作目录

二、步骤二:docker build现在有了 Dockerfile 这张“施工图纸”,我们就可以请出“施工队”了,用 docker build 命令来创建出镜像:
docker build 
	-f 指定dockerfile文件,
另外关于 Dockerfile,一般应该在命令行里使用 -f 来显式指定。但如果省略这个参数,docker build 就会在当前目录下找名字是 Dockerfile 的文件。所以,如果只有一个构建目标的话,文件直接叫“Dockerfile”是最省事的。
	-t 也就是指定镜像的标签(tag),这样 Docker 就会在构建完成后自动给镜像添加名字。当然,名字必须要符合上节课里的命名规范,用 : 分隔名字和标签,如果不提供标签默认就是“latest”。
	
docker build -f Dockerfile.busybox .
	回显信息如下
	Sending build context to Docker daemon   7.68kB
	Step 1/2 : FROM busybox
	---> d38589532d97
	Step 2/2 : CMD echo "hello world"
	---> Running in c5a762edd1c8
	Removing intermediate container c5a762edd1c8
	---> b61882f42db7
	Successfully built b61882f42db7
你需要特别注意命令的格式,用 -f 参数指定 Dockerfile 文件名,后面必须跟一个文件路径,叫做“构建上下文”(build’s context),这里只是一个简单的点号,表示当前路径的意思。接下来,你就会看到 Docker 会逐行地读取并执行 Dockerfile 里的指令,依次创建镜像层,再生成完整的镜像。新的镜像暂时还没有名字(用 docker images 会看到是 <none>),但我们可以直接使用“IMAGE ID”来查看或者运行:
docker inspect b61
docker run b61

Ubuntu、Debian、CentOS、Alpine、busybox都是操作系统

注意这里的这个Sending build context to Docker daemon   7.68kB 这个7.68kB其实就是这个.代表的当前目录下的文件总计大小,它作为client会将此目录下的文件发送给docker daemon去进行构建,这样一股脑的打包上传如果你的文件目录指定的比较宽泛或者目录下文件较多就可能导致上传了构建镜像无用的文件,这个时候可以在“构建上下文”目录里再建立一个 .dockerignore 文件语法与 .gitignore 类似,排除那些不需要的文件。
# docker ignore
*.swp
*.sh

4、docker-hub
镜像仓库,术语叫 Registry,直译就是“注册中心”,意思是所有镜像的 Repository 都在这里登记保管,就像是一个巨大的档案馆,Docker Hub 上有官方镜像、认证镜像和非官方镜像的区别,官方镜像在名字后面带有Official image标记,认证镜像带有Verifiedpublisher标记,非官方镜像又分为半官方,比如发布者是某些官方公司比如OpenResty是官方发布的,最后一种就是纯民间了。综合来看选取合适的镜像需要综合判断,除了查看镜像是否为官方认证,我们还应该再结合其他的条件来判断镜像质量是否足够好。做法和 GitHub 差不多,就是看它的下载量、星数、还有更新历史,简单来说就是“好评”数量。
镜像的命名:镜像命名采用用户名/应用名的方式比如bitnami/nginx、ubuntu/nginx,所以,我们在使用dockerpull下载这些非官方镜像的时候,就必须把用户名也带上,否则默认就会使用官方镜像。确定了要使用的镜像还不够,因为镜像还会有许多不同的版本,也就是“标签”(tag)。通常来说,镜像标签的格式是应用的版本号加上操作系统。版本号你应该比较了解吧,基本上都是主版本号 + 次版本号 + 补丁号的形式,有的还会在正式发布前出 rc 版(候选版本,release candidate)Alpine、CentOS 的命名比较简单明了,就是数字的版本号,像这里的 alpine3.15 ,而 Ubuntu、Debian 则采用了代号的形式。比如 Ubuntu 18.04 是bionic,Ubuntu20.04是focal,Debian9是stretch,Debian10是buster,Debian11是bullseye。另外,有的标签还会加上 slim、fat,来进一步表示这个镜像的内容是经过精简的,还是包含了较多的辅助工具。通常 slim 镜像会比较小,运行效率高,而 fat 镜像会比较大,适合用来开发调试。下面我就列出几个标签的例子来说明一下。nginx:1.21.6-alpine,表示版本号是 1.21.6,基础镜像是最新的 Alpine。redis:7.0-rc-bullseye,表示版本号是 7.0 候选版,基础镜像是 Debian 11。node:17-buster-slim,表示版本号是 17,基础镜像是精简的 Debian 10。

上传自己的镜像:
	第一步,你需要在 Docker Hub 上注册一个用户
	第二步,你需要在本机上使用 docker login    命令如下: docker login -u yrs   回车输入密码
	第三步很关键,需要使用 docker tag 命令,给镜像改成带用户名的完整名字,表示镜像是属于这个用户的。或者简单一点,直接用 docker build -t 在创建镜像的时候就起好名字。比如用本地的ngx-app  就这样 docker tag ngx-app chronolaw/ngx-app:1.0  然后再查看也有了
	第四步,用 docker push 把这个镜像推上去   docker push chronolaw/ngx-app:1.0 
	第五步,可以登录 Docker Hub 网站验证一下镜像发布的效果,可以看到它会自动为我们生成一个页面模板,里面还可以进一步丰富完善,比如添加描述信息、使用说明等等

离线环境该怎么办:
1、自己搭建私有 Registry 服务,有很多成熟的解决方案,比如 Docker Registry,还有 CNCF Harbor
2、手动下载与上传,docker save/load

5、linux基础知识
linux 文件颜色的含义,蓝色代表目录,绿色代表可执行文件,红色表示压缩文件,浅蓝色表示链接文件,灰色表示其他文件,红色闪烁表示链接的文件有问题了,黄色表示设备文件。
蓝色文件----------目。录
白色文件----------一般性文件,如文本文件,配置文件,源码文件等。
浅蓝色文件----------链接文件,主要是使用ln命令建立的文件。
绿色文件----------可执行文件,可执行的程序。
红色文件-----------压缩文件或者包文件。

netstat -apn | grep 9091  查看端口占用情况,ubuntu的命令 kill -9 pid 可以杀死进程停止占用

curl 是一种命令行工具,作用是发出网络请求,然后获取数据,显示在"标准输出"(stdout)上面  -i 参数可以显示 http response 的头信息,连同网页代码一起。-I 参数则只显示 http response 的头信息。

cat /etc/os-release  查看当前操作系统,可以看到各个容器之间是隔离不同的

uname -a 查看系统内核,这个可以看到各个容器之间都是用的ubuntu这个虚拟机的内核

运行起来nginx进程后,可以在宿主机上查看到容器的进程,当容器停止,进程小时查看命令 ps -ef | grep nginx 。这说明容器就是虚拟机中的不同进程而已和虚拟机其他进程一样。

6、docker与外界网络互通
docker cp或者利用docker run -v 可以实现虚拟机与容器的文件互通,那么网络互通又该如何实现呢,Docker提供了三种网络模式,分别是null、host和bridge。null是最简单的模式,也就是没有网络,但允许其他的网络插件来自定义网络连接,这里就不多做介绍了。host 的意思是直接使用宿主机网络,相当于去掉了容器的网络隔离(其他隔离依然保留),所有的容器会共享宿主机的 IP 地址和网卡。这种模式没有中间层,自然通信效率高,但缺少了隔离,运行太多的容器也容易导致端口冲突。host 模式需要在 docker run 时使用 --net=host 参数,下面我就用这个参数启动 Nginx:docker run -d --rm --net=host nginx:alpine 然后使用 ip addr # 本机查看网卡 docker exec xxx ip addr # 容器查看网卡 两者一致
第三种 bridge,也就是桥接模式,它有点类似现实世界里的交换机、路由器,只不过是由软件虚拟出来的,容器和宿主机再通过虚拟网卡接入这个网桥(图中的 docker0),那么它们之间也就可以正常的收发网络数据包了。不过和 host 模式相比,bridge 模式多了虚拟网桥和网卡,通信效率会低一些。和 host 模式一样,我们也可以用 --net=bridge 来启用桥接模式,但其实并没有这个必要,因为 Docker 默认的网络模式就是 bridge,所以一般不需要显式指定。docker run -d --rm nginx:alpine # 默认使用桥接模式 docker run -d --rm redis # 默认使用桥接模式 此处需要注意使用的基础镜像是否支持,ip addr 比如redis就不支持 。docker exec xxx ip addr 可以查看到容器的网址是172.17.0.2 而虚拟机本身是172.17.0.1 ,这样相当于虚拟机已经是三块网卡,一块连接外网,一块与本机之间通信(本地台式机也是同样双网卡),一块与容器之间通信,并且同样的容器可以访问百度,只不过经过了两次转发,本地延时七八ms容器延时九ms。另外验证的话也可以通过,docker inspect xxx |grep IPAddress 这样对于不支持IP addr的一样通用。需要注意大小写,可以看到两个ip分别是172.17.0.2、172.17.0.3

7、如何分配服务端口号
服务器应用都必须要有端口号才能对外提供服务,比如 HTTP 协议用 80、HTTPS 用 443、Redis 是 6379、MySQL 是3306,一台主机上的端口号数量是有限的,而且多个服务之间还不能够冲突,但我们打包镜像应用的时候通常都使用的是默认端口,容器实际运行起来就很容易因为端口号被占用而无法启动。解决这个问题的方法就是加入一个“中间层”,由容器环境例如 Docker 来统一管理分配端口号,在本机端口和容器端口之间做一个“映射”操作,容器内部还是用自己的端口号,但外界看到的却是另外一个端口号,这样就很好地避免了冲突。端口号映射需要使用 bridge 模式,并且在 docker run 启动容器时使用 -p 参数,形式和共享目录的 -v 参数很类似,用 : 分隔本机端口和容器端口。比如,如果要启动两个 Nginx 容器,分别跑在 80 和 8080 端口上:docker run -d -p 80:80 --rm nginx:alpine docker run -d -p 8080:80 --rm nginx:alpine 可以直接使用netstat -apn查看虚拟机前后的比对发现之前没有开启对应的80以及8080 之后就开启了。也可以使用curl验证,命令 curl 127.1:80 -I curl 127.1:8080 -I 可以看到对应响应头的的200状态码。 127.1是127.0.0.1的域名他俩是一样的。第三种方式还可以直接通过docker ps中的ports 列直观的看到端口映射信息。

8、计算机网络支持
为了便于对IP地址进行管理, 根据IPv4地址的第一个字节,IPv4地址可以分为以下五大类。A类:0~127。 B类:128191。C类:192223。D类:224239,组播地址。E类:240254,保留为研究测试使用。

9、镜像私服简单搭建:
Docker Registry,第一步 使用 docker pull registry 拉取registry镜像,docker run -d -p 5000:5000 registry 直接启动容器并使用默认的5000 。部署完成继续测试 docker tag nginx:alpine 127.0.0.1:5000/nginx:alpine 先将将要上传的镜像使用tag 拷贝一份,具备了仓库名字之后就可以上传了,后续拉取的时候要先指定镜像仓库地址。 docker push 127.0.0.1:5000/nginx:alpine 传输完了我们可以删除本地再下载 docker rmi 127.0.0.1:5000/nginx:alpine docker pull 127.0.0.1:5000/nginx:alpine 发现正常。另外很重要的是,Docker Registry 虽然没有图形界面,但提供了 RESTful API(官方网址:https://docs.docker.com/registry/spec/api/),比如 curl 127.1:5000/v2/_catalog 获取镜像列表 curl 127.1:5000/v2/nginx/tags/list Nginx 镜像的标签列表信息。

10、搭建 WordPress 网站
网站需要用到三个容器:WordPress、MariaDB、Nginx,它们都是非常流行的开源项目
docker pull wordpress:5
docker pull mariadb:10
docker pull nginx:alpine

先来运行 MariaDB。根据说明文档,需要配置“MARIADB_DATABASE”等几个环境变量,用 --env 参数来指定启动时的数据库、用户名和密码,这里我指定数据库是“db”,用户名是“wp”,密码是“123”,管理员密码(root password)也是“123”。
docker run -d --rm \
	--env MARIADB_DATABASE=db \
	--env MARIADB_USER=wp \
	--env MARIADB_PASSWORD=123 \
	--env MARIADB_ROOT_PASSWORD=123 \
	mariadb:10
启动之后,我们还可以使用 docker exec 命令,执行数据库的客户端工具“mysql”,验证数据库是否正常运行:docker exec -it 9ac mysql -u wp -p  输入刚才设定的用户名“wp”和密码“123”之后,我们就连接上了 MariaDB,可以使用 show databases; 和 show tables; 等命令来查看数据库里的内容。当然,现在肯定是空的。因为 Docker 的 bridge 网络模式的默认网段是“172.17.0.0/16”,宿主机固定是“172.17.0.1”,而且 IP 地址是顺序分配的,所以如果之前没有其他容器在运行的话,MariaDB 容器的 IP 地址应该就是“172.17.0.2”,这可以通过 docker inspect 命令来验证:docker inspect 9ac |grep IPAddress

现在数据库服务已经正常,该运行应用服务器 WordPress 了,它也要用 --env 参数来指定一些环境变量才能连接到 MariaDB,注意“WORDPRESS_DB_HOST”必须是 MariaDB 的 IP 地址,否则会无法连接数据库:
docker run -d --rm \
	--env WORDPRESS_DB_HOST=172.17.0.2 \
	--env WORDPRESS_DB_USER=wp \
	--env WORDPRESS_DB_PASSWORD=123 \
	--env WORDPRESS_DB_NAME=db \
	wordpress:5
WordPress 容器在启动的时候并没有使用 -p 参数映射端口号,所以外界是不能直接访问的,我们需要在前面配一个 Nginx 反向代理,把请求转发给 WordPress 的 80 端口。配置 Nginx 反向代理必须要知道 WordPress 的 IP 地址,同样可以用 docker inspect 命令查看,如果没有什么意外的话它应该是“172.17.0.3”,所以我们就能够写出如下的配置文件(Nginx 的用法可参考其他资料,这里就不展开讲了):
server {
  listen 80;
  default_type text/html;

  location / {
	  proxy_http_version 1.1;
	  proxy_set_header Host $host;
	  proxy_pass http://172.17.0.3;
  }
}
有了这个配置文件,最关键的一步就来了,我们需要用 -p 参数把本机的端口映射到 Nginx 容器内部的 80 端口,再用 -v 参数把配置文件挂载到 Nginx 的“conf.d”目录下。这样,Nginx 就会使用刚才编写好的配置文件,在 80 端口上监听 HTTP 请求,再转发到 WordPress 应用:
docker run -d --rm \
	-p 80:80 \
	-v `pwd`/wp.conf:/etc/nginx/conf.d/default.conf \
	nginx:alpine	
127.0.0.1:80 验证可以正常登录

相关文章:

  • 按位与最大的最长连续子数组
  • <Linux复习>基础指令下
  • Spring中自定义依赖注入对象注入Controller中,优雅的解决用户鉴权问题(HandlerInterceptorAdapter)
  • opencv 车牌识别
  • [LeetCode周赛复盘] 第 312 场周赛20220925
  • 基于HTML+CSS+JavaScript的MIUI10官网网站设计与开发
  • Vue 新手期练手出现问题记录与解决方案——Vue练手项目“小问题“
  • 计算机组成原理-华科版本
  • 计算机网络原理 谢希仁(第8版)第五章习题答案
  • 记一次Netty堆外内存溢出OutOfDirectMemoryError
  • 设计模式详解:模式汇总与索引清单
  • SpringSecurity实战-第5章 自动登录和注销登录
  • Python基础内容训练9(文件操作)
  • 冰冰学习笔记:list的简单模拟
  • 基于鸽群优化算法的线性规划求解matlab程序
  • 3.7、@ResponseBody 和 @RestController
  • CSS魔法堂:Absolute Positioning就这个样
  • JavaScript 一些 DOM 的知识点
  • mockjs让前端开发独立于后端
  • php中curl和soap方式请求服务超时问题
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • SwizzleMethod 黑魔法
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • Vue.js 移动端适配之 vw 解决方案
  • Vue官网教程学习过程中值得记录的一些事情
  • Webpack 4 学习01(基础配置)
  • 力扣(LeetCode)21
  • 判断客户端类型,Android,iOS,PC
  • 前端临床手札——文件上传
  • 前言-如何学习区块链
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 追踪解析 FutureTask 源码
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (¥1011)-(一千零一拾一元整)输出
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (十)c52学习之旅-定时器实验
  • (一)Linux+Windows下安装ffmpeg
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • (轉貼) UML中文FAQ (OO) (UML)
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • ***原理与防范
  • .NET 读取 JSON格式的数据
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET/C# 使用反射注册事件
  • .net程序集学习心得
  • .NET国产化改造探索(一)、VMware安装银河麒麟