Docker上部署一个PHP+MySQL网站的方法

1. 前言

1.1 Docker适合什么类型的项目?

Docker存在的意义是解决项目移植时兼容的问题。
好吧,那么Docker是否对于任何项目都合适呢?
就我目前的体验而言,使用Docker做负载均衡是比较合适的,用Docker装载静态的,较小的项目也是合适的。
如果是想用Docker装载一个大型项目,个人感觉不太合适。这个理论有待后期使用的时候再慢慢探索。

1.2 PHP+MySQL项目部署在Docker的几种思路。

1.2.1 使用tomsik68/xampp

这也是本文要重点探讨的,详情见后面内容。

1.2.2 使用httpd然后再自行安装mysql和php

我会单独写一篇文章记录这个方法。

1.2.3 使用pch18/baota

这种方法是将宝塔软件放在Docker里面。我也会单独写一篇文章记录这个方法。但是这种方法我认为有个致命的问题,就是pch18/baota镜像文件太大了,要5G。你没看错,要5G。所以这种方案的可行性非常值得商榷,因为这很明显违背了Docker存在的意义。

2. 安装部署tomsik68/xampp

下面的内容参考:https://hub.docker.com/r/tomsik68/xampp

2.1 拉取镜像

docker pull tomsik68/xampp

2.2 为宿主机创建mysql数据卷

docker volume create mysql

上述命令的mysql名称任意,为了方便识别用的mysql。

2.3 运行容器

宿主机bind mount网页文件的位置:/opt/www
宿主机映射端口地址:41062
mysql目录不能使用文件夹bind mounts的形式,以下方法执行后会因为权限问题报错。

docker run --name myXampp -p 41061:22 -p 41062:80 -it -v /opt/www:/www -v /opt/mysql:/opt/lampp/var/mysql tomsik68/xampp

必须使用下方数据卷的方法:

docker run --name myXampp -p 41061:22 -p 41062:80 -it -v /opt/www:/www -v mysql:/opt/lampp/var/mysql tomsik68/xampp

2.4 测试运行

在/opt/www 中新建index.php文件,写入如下代码:

<?php
echo "hello world";
echo 1+3;
?>

然后在浏览器中打开地址:http://宿主机IP地址或域名:41062/www/index.php
如果看到hello world4,证明容器运行成功了!
如果运行不成功,可能是因为宿主机防火墙问题,或者关闭防火墙,或者放行41062端口即可。

2.5 进入容器查看

如果想要查看容器内部情况,使用以下命令:

docker exec -it myXampp bash

3. 导入一个PHP+MYSQL网站

我们就以安装一个“帝国CMS”为例演示网站导入过程。

3.1 下载解压安装包。

进入/opt/www目录后下载安装包

wget http://ecms.phome.net/downcenter/empirecms/ecms75/download/EmpireCMS_7.5_SC_UTF8.zip

解压

unzip EmpireCMS_7.5_SC_UTF8.zip

为了方便我把解压后的upload文件夹重名名为了ecms

mv upload ecms

3.2 更改文件夹权限

如果不更改,安装时会提示权限不足。

chmod 777 -R ecms

3.3 完成安装

http://宿主机IP地址或域名:41062/www/ecms/e/install/

按步骤提示完成安装即可。
注:安装时使用xampp默认的mysql用户名:root,密码是空。

4. 数据持久化问题

A. 对于一个web站点,有两部分数据需要持久化:数据库+网页代码。
B. 在tomsik68/xampp给出的官方文档中,run命令是这样写的:

docker run --name myXampp -p 41061:22 -p 41062:80 -d -v /opt/www:/www tomsik68/xampp

上面的命令只实现了网页文件的持久化,没有实现数据库持久化。这样的问题就是每当服务器重启的时候,数据库数据就会丢失。
C. 为了解决数据库持久化的问题,在2.3中我将命令修改为以下形式:

docker run --name myXampp -p 41061:22 -p 41062:80 -it -v /opt/www:/www -v mysql:/opt/lampp/var/mysql tomsik68/xampp

这样,即便服务器重启,只需要使用以下命令就可以重新恢复网站:

docker start myXampp

Docker常用命令

1. 帮助命令

1.1 docker version

显示docker版本信息

1.2 docker info

显示docker详细信息

1.3 docker help

docker帮助

2. 镜像命令

2.1 docker images

显示本地的镜像信息
docker images -a:显示所有镜像(包含中间镜像层)
docker images -q:只显示当前镜像的IMAGE ID
docker images -qa:上面两个组合使用
docker images --digests:显示镜像摘要信息
docker images --no-trunc:显示完整的镜像信息

2.2 docker search

在docker hub上面查找镜像信息
比如:docker search tomcat
docker search -s 30 tomcat:显示star数量超过30的tomcat备选
docker search --no-trunc:显示完整镜像摘要信息
docker search --automated:只显示自动构建的镜像信息

2.3 docker pull

从Docker镜像源仓库中,向本地镜像库中拉取(下载)镜像。
docker pull tomcat:下载tomcat到docker中。

2.4 docker rmi

从本地镜像库中删除某个镜像
docker rmi hello-world:删除hello-world镜像
docker rmi -f hello-world:强制删除hello-world镜像

2.5 docker push

将镜像上传到镜像仓库。示例请见:http://www.moonlightgate.com/archives/270

2.6 docker commit

向本地仓库提交镜像

docker commit -m="描述信息" -a="作者信息" 容器ID 目标镜像名:[标签名]

比如:

docker commit -a="Leon" -m="firstcommit" firsttom royotech/secondtom:1.2
//royotech/secondtom:1.2 意思是 命名空间/镜像名:TAG内容

2.7 docker build

根据Dockerfile构建新的镜像,具体方法见:http://www.moonlightgate.com/archives/267

3. 容器命令

3.1 新建并启动容器

docker run [-OPTIONS] IMAGEID [COMMAND][ARG...]

[OPTIONS]
--name="容器新名字":为容器制定一个名称;
-d:后台运行容器,并返回容器ID,即启动守护式容器;
-i:以交互模式运行容器,通常与-t同时使用;
-t:为容器重新分配一个伪输入终端,通常与-i同时使用;
-P:随机映射端口;
-p:指定端口映射,有以下四种格式:
    - ip:hostPort:containerPort
    - ip::containerPort
    - hostPort:containerPort
    - containerPort

例如1:启动交互式容器:

docker run -it centos

file
例如2:启动守护式容器:

docker run -d centos

例如3:在新建容器的时候给新容器命名

docker run --name=firstdocker -it centos

例如4:后台运行tomcat容器

docker run -d -p 8888:8080 tomcat

例如5:已交互式的方式运行tomcat容器,并映射容器内的Tomcat端口8080至本机Docker的8888端口

docker run -it -p 8888:8080 tomcat

这时就可以通过Docker的IP地址:8888端口访问容器内的tomcat了。

注:关于端口映射后无法在主机访问的问题,请参考:http://www.moonlightgate.com/archives/265

3.2 列出当前所有正在运行的容器

dock ps [-OPTIONS]
-a:列出当前所有正在运行的容器+最近运行过的容器。
-l:显示最近创建的容器。
-n:显示最近n个创建的容器。
-q:静默模式,只显示容器编号。
--no-trunc:不截断输出。

如果运行的时候不加参数,

dock ps

则默认显示当前正在运行的容器。

3.3 退出容器

停止容器并退出:

exit

不停止容器退出:

ctrl+按P+再按Q

3.4 启动容器

docker start 容器ID或容器名

3.5 重启容器

docker restart 容器ID或容器名

3.6 停止容器

docker stop 容器ID或容器名

3.7 强制停止容器

docker kill 容器ID或容器名

3.8 删除已经停止的容器

docker rm 容器ID或容器名

或强制删除

docker rm -f 容器ID或容器名

3.9 查看容器日志

docker logs -f -t --tail 容器ID
-f:动态追加最新的日志
-t:加入时间戳
--tail:最后多少条

比如以追加和显示时间的方式、打印某容器的最后3条日志:

docker logs -f -t --tail 3 容器ID或容器名

3.10 查看容器内运行的进程

docker top 容器ID

3.11 查看容器内部的细节

docker inspect 容器ID

3.12 可以在不进入容器的情况下,在容器里执行命令并返回结果

docker exec -t 容器ID 需要执行的命令

如果需要进入容器,则可以使用以下命令:

docker exec -t 容器ID /bin/bash

3.13 进入容器,通过命令进行交互

进入容器,执行命令:

docker attach 容器ID

如果容器正在执行命令,比如tomcat,则此种方式无法进入命令行,还需要使用exec方式才能进入命令行。

3.14 从容器内复制文件到主机上

docker cp 容器ID:路径/文件 主机路径/文件

将Docker镜像推送至Aliyun详细步骤

1. 登陆Aliyun账号。

2. 开通镜像服务。

开通方法请见:http://www.moonlightgate.com/archives/250

3. 创建镜像仓库。

3.1 填写基本信息

file

3.2 创建本地仓库

file

4. 从管理信息里面找到push信息。

file
按照提示运行如下三行代码即可:

$ sudo docker login --username=leon@royotech.com registry.cn-beijing.aliyuncs.com
$ sudo docker tag [ImageId] registry.cn-beijing.aliyuncs.com/royotech/dev_repository:[镜像版本号]
$ sudo docker push registry.cn-beijing.aliyuncs.com/royotech/dev_repository:[镜像版本号]

注意:提示输入密码时要填写第2步开通镜像服务时设定的密码。

Dockerfile理解与Dockerfile指令与Dockerfile构建方法

Dockerfile

Dockerfile是用来构建Docker镜像的构建文件。
是由一系列命令和参数构成的脚本文件。

Dockerfile构建步骤

  1. 编写Dockerfile文件
  2. 构建Docker镜像:docker build
  3. 生成Docker容器:docker run

Dockerfile构建语法格式

  1. 每条保留字指令必须为全大写字母,且后面至少要跟一个参数。
  2. 指令按照从上到下顺序执行。
  3. #代表当前行注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交。

Dockerfile保留关键字

FROM

基础镜像,当前镜像是基于哪个镜像的

MAINTAINER

该镜像的作者+邮箱信息

RUN

构建容器时需要执行的命令

EXPOSE

镜像变为实例对外暴露的端口号

WORKDIR

实例登陆后的工作目录;如果不指定,默认为根目录。

ENV

设置镜像的环境变量

COPY

复制文件到镜像中。

ADD

将宿主机目录下的文件复制到镜像,且ADD命令会自动处理URL和解压tar压缩包。

VOLUME

指定容器的数据卷用于持久化

CMD

指定一个容器启动时要运行的命令(替换式)。
CMD会被docker run之后的参数替换。

ENTRYPOINT

指定一个容器启动时要运行的命令(追加式)。
ENTRYPOINT会被docker run之后的参数追加。

ONBUILD

当构建一个被继承的Dockerfile时,父镜像在被继承后父镜像的ONBUILD指令被处罚。

案例:为默认的CentOS镜像增加vim和ifconfig功能

  1. 宿主机任意地方新建Dockerfile文件。
    比如:/myDocker/Dockerfile
    文件内容如下:
FROM centos
MAINTAINER Leon<leon@royotech.com>

ENV mypath /usr/local
WORKDIR $mypath

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

EXPOSE 80

CMD /bin/bash
  1. 构建镜像。
docker build -f /myDocker/Dockerfile -t centos1.1 .
  1. 生成容器。
docker run -it centos1.1

新生成的容器中,可以直接使用vim和ifconfig了。哈哈哈!

Docker容器数据卷理解和使用

Docker数据卷的理解

Docker容器默认是存货在内存中的,当docker容器关闭后,里面的运行数据将丢失。

Docker数据卷的存在意义有两个:

  1. 实现docker容器数据的持久化问题。
  2. 实现docker容器与容器、容器与主机的数据交换。

Docker数据卷的使用方法

方法一:命令添加

docker run -it -v /宿主机目录路径:/容器内目录路径[:ro] 镜像名
//如果目录路径不存在则自动创建
//[:ro]只读选项

方法二:DockerFile添加

第一步:

根目录下新建/mydocker/Dockerfile文件。

第二步:

在Dockerfile中撰写VOLUME指令,为镜像添加数据卷。

FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "OK!OK!"
CMD /bin/bash

第三步:

生成镜像文件。

docker build -f /mydocker/Dockerfile -t royotech/centos .

第四步:

根据新镜像生成容器。会在宿主机上自动生成对应的数据卷

容器间数据共享

docker run -it --name dc01 royotech/centos
docker run -it --name dc02 --volumes-from dc01 royotech/centos

//--volumes-from dc01 以继承dc01的形式,实现dc01和dc02间的数据共享

CentOS8中Docker容器端口映射后宿主机无法访问的问题

问题描述

  1. IP地址是 http://192.168.81.143 的主机上安装了CentOS8。
  2. CentOS8里面安装了Docker,并使用docker run命令从tomcat镜像创建新容器并映射端口:
    docker run --name=firsttom -it -p 8888:8080 tomcat
  3. 按道理,在主机使用 http://http://192.168.81.143:8888 应该能够访问firsttom容器的tomcat才对,然而却无法访问。

解决过程

  1. 首先想到的就是防火墙问题。于是我在主机上关闭了防火墙:
    systemctl stop firewalld

    别说,这样一来firsttom容器的tomcat还真可以访问了。

  2. 我不想关闭防火墙,所以就想到把8888端口在防火墙里面放行:
    firewall-cmd --zone=public --add-port=8066/tcp --permanent
    firewall-cmd --reload

    按道理这样就应该能访问了,然而防火墙打开后,发现仍然无法访问。

  3. 于是乎就开始了各种搜索,排除了各种不靠谱方案后,终于找到解决方法:
    # 把docker0网卡添加到trusted域
    firewall-cmd --permanent --zone=trusted --change-interface=docker0
    # 重启加载配置
    firewall-cmd --reload

注:这个方法对CentOS7也有效

什么是Docker?Docker在CentOS8下的安装方法

什么是Docker?

file
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。(源自:百度百科)

为什么用Docker?

Docker最直接的应用就是解决:“开发人员和运维人员打架的问题”。

我们经常会遇到这样一种场景:开发人员做了许久的项目,在自己的开发环境下测试了千百遍确认无误后交给了运维人员,运维人员部署到服务器上后出现各种问题,然后开发人员和运维人员就开始互相扯皮了。

出现这种问题的原因主要是运维人员部署的环境可能和开发人员的开发环境有差异。

Docker就能很好的解决这个问题!

每一个Docker镜像可以创建多个容器,每个容器就是一个“麻雀虽小五脏俱全”的操作系统,里面包含了一个软件系统,以及这个软件系统所有依赖的运行环境。

Docker的镜像原理

Docker的镜像是累积式的层级结构。
Docker的所有镜像都共用Docker的底层内核,并在底层内核基础上累积其它内容。
这种机制会使得Docker的镜像文件大小会出现“偏大”或“偏小”的问题,比如:

  • CentOS只有200M:因为CentOS底层使用了Docker内核,所以大小精简了很多。
  • Tomcat却有近500M:因为Tomcat想要运行,必须前提是有Linux系统、JDK运行环境等等。所以Tomcat里面其实是包含了运行Tomcat的所有环境。

DockerHub

Docker的远程镜像地址库,一般用来查询镜像信息。
网址:https://hub.docker.com/

Docker在CentOS8的安装

1. Docker的版本。

Docker分为CE(Community Edition)免费和EE(Enterprise Edition)收费两个版本。我们以安装CE版本为例。

官方参考文档:https://docs.docker.com/install/linux/docker-ce/centos/

2. 如果之前装过Docker,则卸载老版本

$ sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

3. 安装Docker仓库

$ yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
$ yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

4. 安装Docker

yum install docker-ce docker-ce-cli containerd.io

可能会报以下错误:

package docker-ce-3:19.03.5-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of the providers can be installed

Docker是运行在containerd.io容器里的,上面的错误意思是containerd.io版本太低了。所以呢,要把上面的命令拆成两部分:

第一部分:安装更高版本的containerd.io

yum install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm

第二部分:安装docker-ce和docker-ce-cli

yum install docker-ce docker-ce-cli

5. 启动Docker服务

systemctl start docker

6. HelloWorld测试

docker run hello-world

看到下面内容,证明安装成功:
file

7. 设置Docker的Aliyun镜像加速器

7.1 注册登陆阿里云账号。

自己完成吧。

7.2 搜索并开通容器镜像服务。

阿里云的东西多到爆,别傻傻的一个一个找,在以下位置搜索“镜像”,然后点击搜索结果“容器镜像服务”。

file

按照提示,设置“设置Registry登录密码”

file

7.3 获取镜像相关信息并按照提示进行配置文件修改。

file
第一步:新建/etc/docker/daemon.json文件。
第二步:将阿里云里面提示的内容写入daemon.json文件中。

{
  "registry-mirrors": ["https://XXX.mirror.aliyuncs.com"]
}

第三步:重新加载和运行docker命令。

sudo systemctl daemon-reload
sudo systemctl restart docker

误区提醒:
在某个版本的教程里面,会教你用ps命令查看当前docker进程:

ps -ef|grep docker

如果查询结果里面出现了aliyun的地址,才算配置成功。
我当时按照这个方法操作后,就是没有在进程出现Aliyun的信息,所以就一直认为自己的镜像没有配置成功。
其实,在CentOS7和CentOS8里面,设置成功后,在进程中你根本看不见Aliyun的信息。只有在CentOS6.5中才能看见,而且CentOS6.5的配置方法也和后续版本不一样。
那个录制教程的傻子自己都没有试过就瞎BB一通!害我浪费了大把时间!