如何编写 Dockerfile 文件创建 Docker 镜像

一、前言

承接上篇文章 docker 镜像与容器,本篇来讲讲如何创建 Dockerfile 来构建一个镜像。上篇文章有讲到构建一个自定义镜像是手动去构建的,虽然步骤清晰,但是操作比较繁琐,镜像分发起来也不是很方便,所以有必要用一种更好的办法去替换这种模式去创建自定义镜像,于是 Dockerfile 就是最优替代方案。废话少说,现在就来看看如何编写一个 Dockerfile 文件并创建容器镜像的,先说明一个本篇文章的运行环境吧,有看过上篇文章的朋友应该知道,我用的 docker 的镜像加速地址是阿里云的,我觉得这是我用 docker 最无痛的环境了。

二、Dockerfile 示例

# Base images 基础镜像
FROM centos

#MAINTAINER 维护者信息
MAINTAINER lorenwe 

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  文件放在当前目录下,拷过去会自动解压
ADD nginx-1.13.7.tar.gz /tmp/

#RUN 执行以下命令
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 
    && yum update -y 
    && yum install -y vim less wget curl gcc automake autoconf libtool make gcc-c++ zlib zlib-devel openssl openssl-devel perl perl-devel pcre pcre-devel libxslt libxslt-devel 
    && yum clean all 
    && rm -rf /usr/local/src/*
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /tmp/nginx-1.13.7

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install

RUN cd / && rm -rf /tmp/

COPY nginx.conf /usr/local/nginx/conf/

#EXPOSE 映射端口
EXPOSE 80 443

#ENTRYPOINT 运行以下命令
ENTRYPOINT ["nginx"]

#CMD 运行以下命令
CMD ["-h"]

以上代码示例是我编写的一个认为很有代表性的 dockerfile 文件,涉及到的内容不多,但基本上把所有 dockerfile 指令都用上了,也包含一些细节方面的东西,为了达到示例的效果所以并不是最简洁的 dockerfile,建立一个文件夹将以上 dockerfile 放在该文件内,再去 nginx 官网把 nginx 源码包下来放到该文件夹内,之后再在该文件夹内打开命令行窗口,最好是以管理员权限打开命令行窗口,以免出现一些权限问题的错误,此时的目录结构应该是以下样子的

未分类

三、指令分析

FROM 表示的是这个 dockerfile 构建镜像的基础镜像是什么,有点像代码里面类的继承那样的关系,基础镜像所拥有的功能在新构建出来的镜像中也是存在的,一般用作于基础镜像都是最干净的没有经过任何三方修改过的,比如我用的就是最基础的 centos,这里有必要说明一下,因为我用的镜像加速源是阿里云的,所以我 pull 下来的 centos 是自带阿里云的 yum 源的镜像,如果你用的不是阿里云的镜像加速源,pull 下来的镜像 yum 源也不一样,到时 yum 安装软件的时候可能会遇到很多问题(你懂得)。

MAINTAINER 就是维护者信息了,填自己名字就可了,不用说什么了

ENV 设置环境变量,简单点说就是设置这个能够帮助系统找到所需要运行的软件,比如我上面写的是 “ENV PATH /usr/local/nginx/sbin:$PATH”,这句话的意思就是告诉系统如果运行一个没有指定路径的程序时可以从 /usr/local/nginx/sbin 这个路径里面找,只有设置了这个,后面才可以直接使用 ngixn 命令来启动 nginx,不然的话系统会提示找不到应用。

ADD 顾名思义,就是添加文件的功能了,但是他比普通的添加做的事情多一点,源文件可以是一个文件,或者是一个 URL 都行,如果源文件是一个压缩包,在构建镜像的时候会自动的把压缩包解压开来,示例我写的是 ‘ADD nginx-1.13.7.tar.gz /tmp/’ 其中 nginx-1.13.7.tar.gz 这个压缩包是必须要在 dockefile 文件目录内的,不在 dockerfile 文件目录内的 比如你写完整路径 D:test/nginx-1.13.7.tar.gz 都是会提示找不到文件的。

RUN 就是执行命令的意思了,RUN 可以执行多条命令, 用 && 隔开就行,如果命令太长要换行的话在末尾加上 ‘’ 就可以换行命令,RUN 的含义非常简单,就是执行命令,但其中有一些细节还是需要注意的,现在就通过上面的示例来看看需要注意的地方有哪些吧。其中 RUN rpm –import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 的作用就是导入软件包签名来验证软件包是否被修改过了,为做到安全除了系统要官方的之外软件也要保证是可信的。yum update -y 升级所有包,改变软件设置和系统设置,系统版本内核都升级,我们知道 linux 的软件存在依赖关系,有时我们安装新的软件他所依赖的工具软件也需要是最新的,如果没有用这个命令去更新原来的软件包,就很容易造成我们新安装上的软件出问题,报错提示不明显的情况下我们更是难找到问题了,为避免此类情况发生我们还是先更新一下软件包和系统,虽然这会使 docker 构建镜像时变慢但也是值得的,至于后面的命令自然是安装各种工具库了,接着来看这句 yum clean all ,把所有的 yum 缓存清掉,这可以减少构建出来的镜像大小,rm -rf /usr/local/src/ 清除用户源码文件,都是起到减少构建镜像大小的作用。RUN 指令是可以分步写的,比如上面的 RUN 可以拆成以下这样:

# 不推荐
RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 
RUN yum update -y 
RUN yum install -y vim less wget curl gcc automake autoconf libtool make gcc-c++ zlib zlib-devel openssl openssl-devel perl perl-devel pcre pcre-devel libxslt libxslt-devel 
RUN yum clean all 
RUN rm -rf /usr/local/src/*

这样也是可以的,但是最好不要这样,因为 dockerfile 构建镜像时每执行一个关键指令都会去创建一个镜像版本,这有点像 git 的版本管理,比如执行完第一个 RUN 命令后在执行第二个 RUN 命令时是会在一个新的镜像版本中执行,这会导致 yum clean all 这个命令失效,没有起到精简镜像的作用,虽然不推荐多写几个 RUN,但也不是说把所有的操作都放在一个 RUN 里面,这里有个原则就是把所有相关的操作都放在同一个 RUN 里面,就比如我把 yum 更新,安装工具库,清除缓存放在一个 RUN 里面,后面的编译安装 nginx 放在另外一个 RUN 里面。

WORKDIR 表示镜像活动目录变换到指定目录,就相当于 linux 里面 cd 到指定目录一样,其实完全没有必要使用这个指令的,在需要时可以直接使用 cd 命令就行,因为这里使用了 WORKDIR,所以后面的 RUN 编译安装 nginx 不用切换目录,讲到这里又想起了另外一个问题,如下:

RUN cd /tmp/nginx-1.13.7

RUN ./configure

RUN ./configure这样可不可以呢,我想前面看懂的朋友应该知道答案了吧,这里还是再啰嗦一下,这样是会报找不到 configure 文件错误的,原因很简单,因为这个两个命令都不是在同一个镜像中执行的,第一个镜像 cd 进入的目录并不代表后面的镜像也进入了。
COPY 这个指令很简单,就是把文件拷贝到镜像中的某个目录,注意源文件也是需要在 dockerfile 所在目录的,示例的意思是拷贝一份 nginx 配置文件,现在就在 dockerfile 所在目录创建这个文件

user  www;
worker_processes  2;
daemon off;

pid        logs/nginx.pid;

events {    
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

配置很简单,就是对官方的配置文件把注释去掉了,注意里面的 daemon off; 配置,意思是关闭 nginx 后台运行,原因在上一篇文章中讲过,这里再来絮叨一下,容器默认会把容器内部第一个进程是否活动作为docker容器是否正在运行的依据,如果 docker 容器运行完就退出了,那么docker容器便会直接退出,docker run 的时候把 command 作为容器内部命令,如果使用 nginx,那么 nginx 程序将后台运行,这个时候 nginx 并不是第一个执行的程序,而是执行的 bash,这个 bash 执行了 nginx 指令后就挂了,所以容器也就退出了,如果我们设置了 daemon off 后启动 nginx 那么 nginx 就会一直占用命令窗口,自然 bash 没法退出了所以容器一直保持活动状态。

EXPOSE 示例注释写的是映射端口,但我觉得用暴露端口来形容更合适,因为在使用 dockerfile 创建容器的时候不会映射任何端口,映射端口是在用 docker run 的时候来指定映射的端口,比如我把容器的 80 端口映射到本机的 8080 端口,要映射成功就要先把端口暴露出来,有点类似于防火墙的功能,把部分端口打开。

ENTRYPOINT 和 CMD 要放在一起来说,这两者的功能都类似,但又有相对独特的地方,他们的作用都是让镜像在创建容器时运行里面的命令。当然前提是这个镜像是使用这个 dockerfile 构建的,也就是说在执行 docker run 时 ENTRYPOINT 和 CMD 里面的命令是会执行的,两者是可以单独使用,并不一定要同时存在,当然这两者还是有区别的。

先从 CMD 说吧,CMD 的一个特点就是可被覆盖,比如把之前的 dockerfile 的 ENTRYPOINT 这一行删除,留下 CMD 填写[“nginx”],构建好镜像后直接使用 docker run lorenwe/centos_nginx 命令执行的话通过 docker ps 可以看到容器正常运行了,启动命令也是 “ngixn”,但是我们使用 docker run lorenwe/centos_nginx bin/bash 来启动的话通过 docker ps 查看到启动命令变成了 bin/bash,这就说明了 dockerfile 的 CMD 指令是可被覆盖的,也可以把他看做是容器启动的一个默认命令,可以手动修改的。

而 ENTRYPOINT 恰恰相反,他是不能被覆盖,也就是说指定了值后再启动容器时不管你后面写的什么 ENTRYPOINT 里面的命令一定会执行,通常 ENTRYPOINT 用法是为某个镜像指定必须运行的应用,例如我这里构建的是一个 centos_nginx 镜像,也就是说这个镜像只运行 ngixn,那么我就可以在 ENTRYPOINT 写上[“nginx”],有些人在构建自己的基础镜像时(基础镜像只安装了一些必要的库)就只有 CMD 并写上 [‘bin/bash’],当 ENTRYPOINT 和 CMD 都存在时 CMD 中的命令会以 ENTRYPOINT 中命令的参数形式来启动容器,例如上面的示例 dockerfile,在启动容器时会以命令为 nginx -h 来启动容器,遗憾的是这样不能保持容器运行,所以可以这样启动 docker run -it lorenwe/centos_nginx -c /usr/local/nginx/conf/nginx.conf,那么容器启动时运行的命令就是 nginx -c /usr/local/nginx/conf/nginx.conf,是不是很有意思,可以自定义启动参数了。

当然还有一些没有用到的指令:

ARG,ARG指令用以定义构建时需要的参数,比如可以在 dockerfile中写上这句 ARG a_nother_name=a_default_value,ARG指令定义的参数,在docker build命令中以 –build -arg a_name=a_value 形式赋值,这个用的一般比较少。

VOLUME,VOLUME指令创建一个可以从本地主机或其他容器挂载的挂载点,用法是比较多的,都知道 docker 做应用容器比较方便,其实 docker 也可做数据容器,创建数据容器镜像的 dockerfile 就主要是用 VOLUME 指令,要讲明 VOLUME 用法有必要在开一篇文章,再此就不做介绍了,
USER,USER用来切换运行属主身份的。docker 默认是使用 root 用户,但若不需要,建议切换使用者身分,毕竟 root 权限太大了,使用上有安全的风险。LABEL,定义一个 image 标签。

四、构建演示

dockerfile 构建镜像的命令很简单,在我的示例中我的命令是 “docker build -t lorenwe/centos_nginx . “,注意后面的点不能省略,表示的从当前目录中寻找 dockerfile 来构建镜像

D:dockerlorenwe>docker build -t lorenwe/centos_nginx .
Sending build context to Docker daemon  995.8kB
Step 1/13 : FROM centos
 ---> d123f4e55e12
Step 2/13 : MAINTAINER lorenwe
 ---> Running in e5c7274f50e8
 ---> 606f7222e69a
Removing intermediate container e5c7274f50e8
Step 3/13 : ENV PATH /usr/local/nginx/sbin:$PATH
 ---> Running in 23716b428809
 ---> 5d8ee1b5a899
         ....
Successfully built eaee6b40b151
Successfully tagged lorenwe/centos_nginx:latest

看到以上内容就说明成功,构建过程可能需要一点点时间,毕竟要安装一些软件,如果你跟我一样是配置的阿里云的容器源构建时应该不会出现什么问题,因为我之前是有拉取过 centos ,所以在 build 时直接使用本地的 centos,如果你没有拉取过 centos,那么在 build 时还会把 centos 拉取下来

D:dockerlorenwe>docker images
REPOSITORY               TAG     IMAGE ID       CREATED          SIZE
lorenwe/centos_nginx     latest  eaee6b40b151   7 minutes ago    427MB
lorenwe/centos_net_tools latest  35f8073cede1   6 days ago       277MB
centos                   latest  d123f4e55e12   3 weeks ago      197MB
d4w/nsenter              latest  9e4f13a0901e   14 months ago    83.8kB

D:dockerlorenwe>docker run -itd --name nginx1 lorenwe/centos_nginx
15d4f108dab7c2f276209ebeb501cac0d3be828e1e81bae22d3fd97c617439eb

D:dockerlorenwe>docker ps
CONTAINER ID    IMAGE    COMMAND     CREATED    STATUS     PORTS     NAMES

D:dockerlorenwe>docker ps -a
CONTAINER ID   IMAGE                 COMMAND    CREATED   STATUS   PORTS   NAMES
15d4f108dab7   lorenwe/centos_nginx  "nginx -h"                            nginx1

D:dockerlorenwe>docker run -itd --name nginx2 lorenwe/centos_nginx -c /usr/local/nginx/conf/nginx.conf
b6b0e962ca3056d67c24145b08975ffddb9cc050fce5f09f65310fb323ffc1c3

D:dockerlorenwe>docker ps
CONTAINER ID   IMAGE                 COMMAND        CREATED    STATUS    PORTS     NAMES
b6b0e962ca30   lorenwe/centos_nginx  "nginx -c /usr/loc..."              80/tcp    nginx2

D:dockerlorenwe>docker run -itd -p 8080:80 --name nginx3 lorenwe/centos_nginx -c /usr/local/nginx/conf/nginx.conf
2f6997745641e3e3edbbfe5213e6235cab3b5a929f116a2c132df504156090c6

D:dockerlorenwe>docker ps
CONTAINER ID   IMAGE                 COMMAND    CREATED   STATUS     PORTS                  NAMES
2f6997745641   lorenwe/centos_nginx  "nginx -c /usr/loc..."          0.0.0.0:8080->80/tcp   nginx3
b6b0e962ca30   lorenwe/centos_nginx  "nginx -c /usr/loc..."          80/tcp                 nginx2

D:dockerlorenwe>docker stop nginx2
nginx2

其中 “docker run -itd -p 8080:80 –name nginx3 lorenwe/centos_nginx -c /usr/local/nginx/conf/nginx.conf” 中的 -p 8080:80 表示把主机的 8080 端口映射到容器的 80 端口,因为之前我们在 dockerfile 中把 80 端口暴露出来了,做好端口映射后现在就可以在主机中打开浏览器访问 127.0.0.1:8080 就能看到 nginx 的欢迎页面了 (^v^).

D:dockerlorenwe>docker run -itd -v D:/docker/lorenwe/html:/usr/local/nginx/html  -p 8081:80 --name nginx4 lorenwe/centos_nginx -c /usr/local/nginx/conf/nginx.conf
cd2d4eb70a39057aed3bfcb64e1f03433e2054d7ff5d50098f49d2e6f2d9e02e

我再在原来的参数中加入了 -v 参数,其作用就是把一个本地主机的目录挂载到容器内部,这个目录是一个共享的状态,两边都可以进行修改,这就是容器的共享卷,其作用就不言而喻了,现在我们在 D:dockerlorenwe 的目录下新建一个叫 html 的文件夹,再在 html 文件夹内新建一个 index.html 随便写上一点内容后再去主机浏览器上访问一下 127.0.0.1:8081 看看是不是你想要看到内容。虽然通过 -v 参数可以满足大部分应用场景,但是 docker 的 VOLUME 还有其他更好用法,欲知后事如何,请看下回分解!

docker离线安装

背景

最近在做私有化部署项目,项目的整体方案基于docker。考虑到客户的运行环境可能无法连接到公网,因此需要制作docker的离线安装。整个离线安装分为三个部分:1)准备docker离线安装包,2)docker离线源配置,3)离线安装docker

准备docker离线安装包

目前只考虑Linux及其发行版的服务器。docker对于机器和操作系统的要求:

  • 内核版本3.10及其以上
  • 操作系统位数为64位
  • CPU架构为x86_64或amd64(目前也有别的支持)
  • 内核开启并支持cgroup和命名空间

简单点说来,常用的 CentOS 7及其以上,Ubuntu 14及其以上,Fedora 24及其以上,Debian 8及其以上,还有 Raspbian 等。这个部分具体可以参考[1]。这个是docker官方的在线安装脚本,本文中的内容主要也是参考这个脚本。

对于不同的操作系统,不同的架构,需要的docker安装包不同,所以要分开处理。目前主流的包管理工具是 apt-get 和 yum,这两者也分别对应到UbuntuDebian和CentOSFedora系列操作系统。不管是哪种包管理工具,基本思路都是

  1. 下载docker安装包及其依赖
  2. 对下载下来的安装包制作本地源
  3. 准备本地源配置文件

对于 apt-get 来说,可以执行以下脚本,该脚本抽取自参考链接[1]。对于流程的解释可以参考链接[2]

#!/bin/sh

lsb_dist="ubuntu"
dist_version="xenial"   # 14-trusty 16-xenial 17-zesty

DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
DOWNLOAD_DIR="/home/work/docker-packages/$lsb_dist-$dist_version"

set -e
apt_repo="deb [arch=$(dpkg --print-architecture)] $DOWNLOAD_URL/linux/$lsb_dist $dist_version stable"

if [ ! -x "$DOWNLOAD_DIR" ]; then
    mkdir -p "$DOWNLOAD_DIR"
fi

apt-get update -qq >/dev/null
apt-get install -y -qq apt-transport-https ca-certificates curl dpkg-dev > /dev/null
curl -fsSL "$DOWNLOAD_URL/linux/$lsb_dist/gpg" | apt-key add - > /dev/null
echo "$apt_repo" > /etc/apt/sources.list.d/docker.list
if [ "$lsb_dist" = "debian" ] && [ "$dist_version" = "wheezy" ]; then
    sed -i "/deb-src.*download.docker/d" /etc/apt/sources.list.d/docker-ce.list
fi
# 只下载docker和依赖的安装包
apt-get update -qq >/dev/null
apt-get --download-only -o Dir::Cache="./" -o Dir::Cache::archives=$DOWNLOAD_DIR install -y --no-install-recommends docker-ce > /dev/null

# 为安装包建立索引,方便后续加载为本地源安装
touch $DOWNLOAD_DIR/Packages.gz
dpkg-scanpackages $DOWNLOAD_DIR /dev/null | gzip > $DOWNLOAD_DIR/Packages.gz

我在制作的时候,对于生成的Packages.gz,调整里面每一个软件的 Filename 项,只留下软件名,不保留前面的目录路径。具体可以使用sed命令。

对于 yum 来说,可以执行以下脚本,该脚本也抽取自参考链接[1]。对于流程的解释可以参考链接[3]

#!/bin/sh

lsb_dist="centos"
dist_version="7"

DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
DOWNLOAD_DIR="/home/work/docker-packages/$lsb_dist-$dist_version"

set -e
yum_repo="$DOWNLOAD_URL/linux/$lsb_dist/docker-ce.repo"

if [ ! -x "$DOWNLOAD_DIR" ]; then
    mkdir -p "$DOWNLOAD_DIR"
fi

# 只下载docker和依赖的安装包
yum-config-manager --add-repo $yum_repo
yum makecache
yum install --downloadonly --downloaddir=$DOWNLOAD_DIR docker-ce

# 为安装包建立索引,方便后续加载为本地源安装
createrepo $DOWNLOAD_DIR

准备docker离线源配置

将刚刚准备好的安装包内容($lsb_dist-$dist_version这个目录下)拷贝到目标机器上,比如统一放到/home/work/docker-packages目录下。基于这个路径:

对于 apt-get 系的离线源配置文件为 docker-ce.list,内容如下

deb [trusted=yes] file:/home/work/docker-packages ./

对于 yum 系的离线源配置文件为 docker-ce.repo,内容如下

[Local_docker_yum]
name=Local Docker Yum Repository
baseurl=file:///home/work/docker-packages/
enabled=1
gpgcheck=0

离线安装docker

对于 apt-get 将离线源配置文件 docker-ce.list 拷贝到 /etc/apt/sources.list.d 目录下。如果电脑不能联网,先将 /etc/apt/sources.list 文件重命名;然后执行apt-get update;再把刚刚重命名的 /etc/apt/sources.list 改回来。如果不这么改的话,在apt-get update的时候可能联网失败而无法完成更新。

最后执行 apt-get install docker-ce

对于 yum 将离线源配置文件 docker-ce.repo 拷贝到 /etc/yum.repos.d/ 目录下。如果电脑不能联网,先将 /etc/yum.repos.d/ 目录下其他配置文件重命名;然后执行 yum makecache;最后再把刚刚重命名的文件改回来。这么做的理由同上。

最后执行 yum install docker-ce

使用 Vagrant 管理虚拟机

未分类
使用 Vagrant 可以很方便的管理虚拟机,只需要一行命令可以操作管理虚拟机,也可以重新打包成新的镜像,分享他人使用。

安装 Vagrant

可以通过 Homebrew 使用命令行安装,可以直接去 Vagrant 官网(https://www.vagrantup.com)下载安装包手动安装。

// 命令行安装 Vagrant
brew install Caskroom/cask/vagrant 

虚拟机需要用到虚拟机软件,比如 Virtualbox,VMware,Parallels Desktop 等等,因为 Virtualbox 开源且免费,所以此处使用 Virtualbox。安装 Virtualbox 同样可以通过命令行或者官网(https://www.virtualbox.org)下载安装包手动安装。

// 命令行安装 Virtualbox
brew install Caskroom/cask/virtualbox

Vagrant Box

Box 是 Vagrant 使用的一种包含虚拟机镜像、虚拟机配置和 Vagrant 配置的封装包文件。在 Vagrant 提供的云服务(https://vagrantcloud.com/)上可以下载到其他人制作好的 Box。

添加 Box

Vagrant 添加 Box 的命令为:

vagrant box add <name>

此处以 CentOS 7 为例,如果指定的 Box 在本地电脑上不存在,Vagrant 会到云上自动下载执行:

vagrant box add centos/7

安装成功后界面如下:

未分类

完成以后,可以查看一下在本地上的 Box 列表:

vagrant box list

也可将 Box 手动下载到本地电脑上,再执行 vagrant box add 命令去手工添加 Box:

vagrant box add <name> <path>

升级 Box

检查是否有可用的升级,执行命令:

vagrant box outdated

返回:

Checking if box 'centos/7' is up to date...

执行升级:

vagrant box update

删除 Box

不再需要的镜像可以从电脑中删除掉,执行:

vagrant box remove <box name>

即使你删除了安装在电脑上的镜像,已经使用这个镜像创建的我虚拟机也仍然是可以正常使用的。不过为了更安全一些,你最好在删除镜像之前 ,先去销毁所有使用了这个镜像创建的虚拟机。

创建虚拟机

添加了 Box 以后,我们就可以用 Vagrant 基于这个 Box 去创建虚拟机了。首先需要创建一个目录,这个目录就是项目所在的目录,它会自动跟虚拟机上的某个目录同步,也就是在你电脑上的这个目录里的文件,同样可以在虚拟机里面的某个目录里找到。

我是在桌面上新建了一个 www 有目录,然后再进入到这个目录:

cd ~/desktop
mkdir www
cd www

然后使用 vagrant init 命令进行初始化,完成以后,在上面建的目录中会创建一个叫 Vagrantfile 的文件。

启动虚拟机

启动虚拟机,执行命令:

vagrant up

完成以后,可以使用 vagrant status 命令来查看虚拟机的状态,如果返回的是 running 说明虚拟机启动成功,现在就可以使用 SSH 连接到虚拟机,去控制它了。

控制虚拟机

使用命令行控制虚拟机,首先需要进入到项目的目录。

连接虚拟机 SSH,执行命令:

vagrant ssh

连接成功后,会返回提示符:

[vagrant@localhost ~]$

退出虚拟机 SSH,执行命令:

exit

暂停虚拟机,执行命令:

vagrant suspend

重新恢复启动,执行命令:

vagrant resume

虚拟机重启,执行命令:

vagrant reload

关闭虚拟机,执行命令:

vagrant halt

删除虚拟机

不打算再用的虚拟机,可以把它删除,直接删除项目的目录是不行的,需要使用命令去删除虚拟机。进行到项目所在目录,然后执行:

vagrant destroy

#EOF

awk获取文本的某一行,某一列

打印文件的第一列(域)  awk '{print $1}' filename
打印文件的前两列(域)  awk '{print $1,$2}' filename
打印完第一列,然后打印第二列  awk '{print $1 $2}' filename
打印文本文件的总行数  awk 'END{print NR}' filename
打印文本第一行       awk 'NR==1{print}' filename
打印文本第二行第一列  sed -n "2, 1p" filename | awk 'print $1'

Bash里面的赋值方法有两种,格式为

1) arg=`(命令)`
2) arg=$(命令)

想要把某一文件的总行数赋值给变量nlines,可以表达为:

1) nlines=`(awk 'END{print NR}' filename)`
或
2) nlines=$(awk 'END{print NR}' filename)

——EOF——

修改Nginx与Apache上传文件大小限制

修改 Nginx 上传文件最大值限制

我们使用 ngnix 做 web server 的时候,nginx 对上传文件的大小有限制。

这个时候我们要修改 nginx 参数。

sudo vim /etc/nginx/nginx.conf 
#在http段里面添加:
client_max_body_size 100m;  //举例设置上传最大值为100m

然后重启nginx

systemctl restart nginx

修改 Apache 上传文件最大值限制

打开 php.ini, 找到下面的项并修改之。下面以上传100M为例。

sudo vim /etc/php.ini
file_uploads = on ;是否允许通过HTTP上传文件的开关。默认为ON即是开 
upload_tmp_dir ;文件上传至服务器上存储临时文件的地方,如果没指定就会用系统默认的临时文件夹 
upload_max_filesize = 100m ;望文生意,即允许上传文件大小的最大值。默认为2M 
post_max_size = 100M ;指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默认为8M

一般地,设置好上述四个参数后,上传<=8M的文件是不成问题,在网络正常的情况下。

但如果要上传>8M的大体积文件,只设置上述四项还一定能行的通。除非你的网络真有100M/S的上传高速,否则你还得关心关心下面的参数:

max_execution_time = 600 ;每个PHP页面运行的最大时间值(秒),默认30秒 
max_input_time = 600 ;每个PHP页面接收数据所需的最大时间,默认60秒 
memory_limit = 128M ;每个PHP页面所吃掉的最大内存,默认8M

全部设置好之后,重启

systemctl restart httpd

CentOS下apache绑定域名

本文主要介绍在CentOS下apache绑定域名以及apache绑定多个域名,首先要找到apache的配置文件httpd.conf的位置。CentOS操作系统一般在 /etc/httpd/conf 下,有的Linux操作系统版本是在 /etc/Apache2/conf 或 /usr/local/etc/apache 文件夹里面,剩下需要做的是修改配置文件httpd.conf,一般配置文件最下面有如下绑定域名说明:

# VirtualHost example:  
# Almost any Apache directive may go into a VirtualHost container.  
# The first VirtualHost section is used for requests without a known  
# server name.  
#  
#<VirtualHost *:80> 
#    ServerAdmin [email protected]  
#    DocumentRoot /www/docs/dummy-host.example.com  
#    ServerName dummy-host.example.com  
#    ErrorLog logs/dummy-host.example.com-error_log  
#    CustomLog logs/dummy-host.example.com-access_log common  
#</VirtualHost> 

大家可以依葫芦画瓢,也可以结合相关语法加入自己的配置说明,下面是我无忧程序的配置文件:1、* 星号修改成自己网站的IP地址 2、ServerAdmin管理员邮箱(可有可无) 3、DocumentRoot网站文件在服务器的目录路径 4、ServerName绑定相应域名 5、ServerAlias泛解析绑定子域名 6、ErrorLog和CustomLog指定日志文件存放路径。

<VirtualHost 175.102.8.117:80> 
    addDefaultCharset gbk  
    DocumentRoot /chengxu 
    ServerName 66php.com  
    ServerAlias *.66php.com  
    ErrorLog /sym/logs/66php.com-error_log  
    CustomLog /sym/logs/66php.com-access_log common  
</VirtualHost> 

如果一个服务器绑定多个域名不是在ServerName添加多个域名,ServerName 后面只能加一个域名,要重复绑定则需要添加多加多个VirtualHost模块。

Apache/Httpd安装mod_pagespeed加速模块

mod_pagespeed是谷歌发布的加速httpd的优化模块,通过自动优化代码、压缩传输内容、自动缓存加速http,支持Centos/Debian系统

Centos/Fedora下安装:

    #http://www.haiyun.me  
    #32位  
    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_i386.rpm  
    #64位  
    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.rpm  
    yum install at  rpm -U mod-pagespeed-*.rpm

Debina/Ubuntu下安装:

    #32位  
    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_i386.deb  
    #64位  
    wget https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.deb  
    dpkg -i mod-pagespeed-*.deb

重启httpd:

service httpd restart

查看pagespeed是否加载:

httpd -M|grep pagespeed

记录一次Tshark使用异常

记录备忘!

使用tshark抓包时,出现以下异常:

Running as user “root” and group “root”. This could be dangerous. 
Capturing on ‘enp3s0’ 
tshark: The file to which the capture would be saved (“tmp1/test.pcap”) could not be opened: Permission denied.

问题描述:

tshark抓包时必须以root身份运行,在普通用户模式下以sudo su 切换到root身份时,运行报错.

问题原因:

ls -lst 查看权限如下:

drwxr-xr-x 2 yk opuser 4096 Dec 4 16:53 tmp1 

该目录的所有者并非root,也没有提供其他用户的使用权。修改目录权限使root拥有写入权限即可.

chmod o+w tmp1 

权限不一定修改为o,同组时也可以使用g.
或者直接使用root身份创建目录.
如果是多级目录,只修改最下一级目录是不能解决问题的,必须将目标路径上的目录的权限全修改.
再次运行即可解决问题.

APACHE显示目录列表的配置方法

我们可以通过修改Apache配置文件httpd.conf来实现显示文件目录列表,代码如下:

    DocumentRoot  "c:www"

    Options Indexes
    AllowOverride All
    Order allow,deny
    IndexOptions Charset=UTF-8
    Allow from all

注意:”D:WWW”是网站的根目录,参数”Options Indexes”表示启用目录浏览,”IndexOptions Charset=UTF-8″设置字符集,以消除中文乱码。

如果是添加的虚拟主机站点,加在虚拟主机配置文件vhosts.conf内修改以下代码:

    Options Indexes
    AllowOverride All
    Order allow,deny
    IndexOptions Charset=UTF-8
    Allow from all

其中”D:www.test.com”为所添加虚拟主机站点的根目录,”Options Indexes”表示启用目录浏览。

修改好,保存,重启Apache服务,就可以了,如下图:

未分类

OpenResty 访问系统环境变量

在编写程序时,我们经常会依据不同的环境使用不同的配置,之前一直以为 OpenResty 无法访问系统的环境变量,所以使用一种很 low 的方式去加载不同环境的配置。现在才发现自己还是对 Nginx 配置了解的不够全。其实 Nginx 的核心功能中就存在一个 env指令,可以实现我们的需求。下面来说明下这个 env 指令。

env

Syntax: env variable[=value];
Context: main

默认情况下,nginx 会移除所有从父进程继承的环境变量,如果你想使用这些环境变量,需要使用该指令显示告知nginx不要移除你指定的环境变量。而且你也可以更改它们的值或创建新的环境变量。

例如

env PROJECT_MODE;
# 也可以使用env PROJECT_MODE=DEV; 来覆盖父进程的环境变量

则 nginx 会保留系统的 PROJECT_MODE 环境变量,
然后在lua脚本中,我们就可以通过 lua 的os.getenv()来获取对应的环境变量了,并依据不同的环境使用不同的配置

# config.lua
local env = os.getenv("PROJECT_MODE")
local config = {}
-- 开发环境配置
if env == "DEV" then

-- 生产环境配置
elseif env == "PROD" then

end

return config