Docker Alpine 镜像设置东八区

背景

最近做了一个alpine镜像,需要打印日志,发现打印出来的日志时间不对,需要对它进行时区设置。

镜像基于postgres:9.4-alpine

什么是 alpine

Alpine Linux Docker 镜像基于 Alpine Linux操作系统,后者是一个面向安全的轻型Linux发行版。不同于通常Linux发行版,Alpine Linux采用了musl libc和busybox以减小系统的体积和运行时资源消耗。在保持瘦身的同时,Alpine Linux还提供了自己的包管理工具apk,可以在其网站上查询,或者直接通过apk命令查询和安装。

Alpine Linux使用了musl,可能和其他Linux发行版使用的glibc实现会有所不同。在容器化中最可能遇到的是DNS问题,即musl实现的DNS服务不会使用resolv.conf文件中的search和domain两个配置,这对于一些通过DNS来进行服务发现的框架可能会遇到问题。

Alpine Linux Docker 镜像主要特点是容量非常小,只有5M,且拥有非常友好的包管理器。

方案

针对我的场景,为 alpine 设置TZ环境变量即可:

FROM postgres:9.4-alpine

ENV TZ=Asia/Shanghai

而相对于原生的alpine系统,可能需要更多的一些工作,例如安装tzdata,具体做法如下:

RUN apk update && apk add ca-certificates && update-ca-certificates && apk add --update tzdata
ENV TZ=Asia/Shanghai
RUN rm -rf /var/cache/apk/*

参考资料


为网站启用https,使用容器化的 Let's Encrypt

背景

去年有记录过一篇 Let’s Encrypt ,不过是基于源码的。最近在为服务器做迁移,将运维组件也容器化。这篇文章记录我使用 容器化 Let’s Encrypt 的过程。更详细的操作步骤可以参考我以前的文章——《Let’s Encrypt》

什么是 Let’s Encrypt

Let’s Encrypt是国外一个公共的免费SSL项目,由 Linux 基金会托管,它的来头不小,由Mozilla、思科、Akamai、IdenTrust和EFF等组织发起,目的就是向网站自动签发和管理免费证书,以便加速互联网由HTTP过渡到HTTPS,目前Facebook等大公司开始加入赞助行列。

Let’s Encrypt已经得了 IdenTrust 的交叉签名,这意味着其证书现在已经可以被Mozilla、Google、Microsoft和Apple等主流的浏览器所信任,你只需要在Web 服务器证书链中配置交叉签名,浏览器客户端会自动处理好其它的一切,Let’s Encrypt安装简单,未来大规模采用可能性非常大。

方案

Let’s Encrypt 分为 StandanloneWebroot 两种认证方式,主要区别在于:

  1. Standalone 的认证方式需要暂时占用服务器的 80 或者 443 端口,来进行获取和更新证书的操作。这意味着网站必须下线才行。
  2. Webroot 认证方式需要在域名配置文件里 server.conf (监听 80 端口那部分)中,添加一个通配规则,使得 certbot 可以生成一个特定的验证文件,同时让之后 Let’s Encrypt 的验证服务器发起的 http-01 请求可以验证到对应文件。

就目前来说我属于比较懒的一类人,目前暂时忍受住了临时下线的问题(网站下线10s左右),standalone较为简单,遂使用了 standalone 的方式。

例如首次认证test.kelu.org这个域名:

docker run -it --rm --name certbot \
  -p 80:80 \
  -v "$(pwd)/data:/etc/letsencrypt" \
  -v "$(pwd)/datalib:/var/lib/letsencrypt" \
  certbot/certbot certonly \
  --standalone \
  --email admin@kelu.org --agree-tos \
  -d test.kelu.org

便在当前目录下的data文件夹里生成好了证书。

证书有三个月的有效期,此时运行renew命令即可续约:

docker run -it --rm --name certbot \
  -p 80:80 \
  -v "$(pwd)/data:/etc/letsencrypt" \
  -v "$(pwd)/datalib:/var/lib/letsencrypt" \
  certbot/certbot renew

nginx相关配置

因为一切都是容器化,nginx的配置也固化在文件中,下面是我的docker-compose.yml配置参考:

  nginx:
    image: openresty/openresty:alpine
    restart: always
    volumes:
      - ./:/var/www/html:rw
      - ./docker/letsencrypt/data:/etc/letsencrypt:rw
      - ./docker/openresty/conf.d:/etc/nginx/conf.d:rw
      - ./docker/openresty/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:rw
      - ./docker/log:/log:rw
    links:
      - "php"
    ports:
      - "80:80"
      - "443:443"

nginx 的配置如下:

server {
    listen       443;
    server_name  test.kelu.org;

    access_log /log/yukari.nginx.maintain.access.log;
    error_log  /log/yukari.nginx.maintain.error.log;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/test.kelu.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.kelu.org/privkey.pem;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
    ssl_prefer_server_ciphers on;

    root         /var/www/html/;

    error_page 404 500 502 503 504 /index.html;
}

改进

本文是一个简单初级的生成证书的方式,可快速部署。

目前有几个待改进的点:

  1. 生成证书需要占用80、443端口,意味着当前业务必须停止。
  2. 证书 renew 也需要停止当前业务。
  3. 目前有以dns认证的方式获取证书,更加方便。

Docker on Windows Operation not permitted

先前分享了一个容器化的开发环境——kelvinblood/docker-lnmp,在 mac 下运行无碍,可是跑到Windows下运行的时候,sock 的文件映射就出了问题:

2018/09/17 02:39:54 [crit] 6#6: *2 connect() to unix:/sock/www.sock failed (2: No such file or directory) while connecting to upstream, client: 10.0.75.1, server: , request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/sock/www.sock:", host: "10.0.75.2:8000"

让我疑惑的是,我还有很多的映射,都是ok的,比如log,怎么单单就这个 sock 出了问题?

谷歌了一番,发现 mongo 项目里也有很多人吐槽这个情况,看来并不是我一个人的问题。众多issue里发现了这个靠谱的中文答案:win10下部署报错:Operation not permitted, terminating #7


腾讯 23 岁安全工程师因黑入新加坡一酒店 Wi-Fi,或判狱三年 | 转

一位中国公民在新加坡出席一次网络安全会议期间,决定黑入他下榻酒店的WiFi。

img

腾讯的23岁安全工程师郑杜涛(音译:Zheng Dutao)很想找出飞龙酒店(Fragrance Hotel)一家分店的WiFi服务器有没有安全漏洞,结果吃上了官司,真是好奇心害死猫。

郑某成功地黑入了这台服务器,并在一篇名为“钻新加坡酒店的空子”的帖子中撰文介绍了始末,他还公布了酒店管理员使用的服务器密码。结果这篇博文引起了新加坡网络安全局(CSA)的注意。

周一(9月24日),郑某因此违法行为在新加坡国家法院被罚5000美元。他对这一项罪名供认不讳:有意披露密码,未经授权擅自访问属于飞龙酒店的数据。法院在对他判决时考虑到了一起类似的罪状。

郑某上个月抵达新加坡参加“夺旗”(Capture the Flag)比赛,这项比赛是在洲际酒店举行的网络安全会议上举办的。参赛的安全专家们各自展示黑客攻击和反黑客能力。

郑某在8月27日入住了位于武吉士的飞龙酒店。一天后,他很好奇,想知道这家酒店的WiFi服务器有没有可能存在安全漏洞。通过谷歌,他成功地搜索到了这家酒店WiFi系统的默认用户ID和密码。

郑某连接到酒店的WiFi网关后,在接下来的三天内执行脚本、解密文件和破解密码,然后闯入了酒店WiFi服务器的数据库。

酒店使用的这款服务器存在一个安全漏洞,郑某钻了该漏洞的空子,最终闯入了服务器。他还试图访问飞龙酒店小印度分店的WiFi服务器,但结果失败了。

郑某在其个人博客上记述了他的攻击步骤。他在博文中公布了飞龙酒店WiFi服务器的管理员密码,还在WhatsApp群聊中共享了那篇博文的URL链接。

助理检察官蒂亚盖什•苏库马兰(Thiagesh Sukumaran)说:“郑某知道,披露这些访问代码后,飞龙酒店WiFi服务器中的安全漏洞很可能会被其他人用于非法目的,有可能给这家连锁酒店造成损失。”

检方表示,自2014年以来,郑某一直在撰写关于服务器漏洞的博客。这是他第一次发文介绍他自己发现的漏洞。

新加坡网络安全局无意中看到了他的这篇博客,立即提醒飞龙酒店的管理层。郑某接到要求后撤下了那篇博文。飞龙酒店IT副总裁于9月1日向警方提交了一份关于这起黑客行为的报告。

检方要求罚款5000美元,指出郑某似乎出于好奇而犯了罪,没有造成“实际的危害”。但助理检察官特别指出,那篇博文在不止一个论坛上共享了。

助理检察官:“作为一名安全专业人士,郑某应该知道,如果在博客上公布管理员密码,不法分子利用密码搞破坏的可能性很大。”

据检方声称,由于其他酒店使用同样款式的服务器,郑某的行为可能导致其他酒店成为网络攻击的受害者,黑客可以获取酒店客人的信息。

助理检查官补充道,这次判罚有助于阻止外国人在未经授权的情况下擅自访问新加坡系统。

郑某律师阿南•纳拉钱德兰(Anand Nalachandran)指出,虽然郑某的行为导致安全风险加大,但是并没有对这家酒店造成实际损害。由于郑某已经被拘留了几天,该律师要求罚款不超过5000美元。

至于在未经授权的情况下披露密码这起罪行,郑某可能因此被判入狱三年,最高罚款10000美元。


使用 docker 构建本地 lnmp 开发环境(Mac)

最近给个人的 mac 重装了系统,所有的配置全部没有了。对 Mac 下的 PHP 不同语言的环境切换还是很头疼的。这篇文章将介绍我使用 docker 部署本地 lnmp 开发环境的整个过程,可以结合我的 github 提交历史了解。业务涉及的知识点有 openresty、php 7.1、laravel、composer、postgresql、redis 等。

本项目也已经开源在 github 上,可以简单使用 docker-compose up -d 命令直接运行起来。

架构

这套环境由前端 openresty 接收请求,通过 linux sock 的方式传给 php-fpm,php-fpm 解析 php 代码,并连接数据库 postgresql 和 redis。

openresty 模块要做好配置文件,与 php-fpm 进行对接。

php-fpm 模块,需要事前编译 postgresql 扩展包。也要做好配置文件,与 openresty 对接。同时代码运行也需要提前使用 composer 进行依赖包的安装,并做好与 postgresql 的配置对接。

postgresql 模块需要准备好 dump 文件,用于首次运行的数据库准备工作。如有需要还要编辑postgresql的配置文件,比如打开慢日志、外部连接等配置。

相关的日志文件保存到 log 文件夹下。

对应的 docker-compose.yml 文件如下:

version:  '3.0'
services:
  nginx:
    image: openresty/openresty:alpine
    volumes:
      - $MYWORKSPACE:/var/www/html
      - ./openresty:/etc/nginx/conf.d
      - ./sock:/sock
      - ./log:/log
    links:
      - "php:php"
    ports:
      - "8000:80"

  php:
    build: ./php
    volumes:
      - $MYWORKSPACE:/var/www/html
      - ./php/php-fpm.d:/usr/local/etc/php-fpm.d
      - ./php/conf/php-fpm.conf:/usr/local/etc/php-fpm.conf
      - ./sock:/sock
      - ./log:/log
    links:
      - "pgsql:pgsql"

  pgsql:
    image: postgres:9.4-alpine
    volumes:
      - ./psql/data:/var/lib/postgresql/data
      - ./psql/dump:/var/lib/postgresql/dump
    ports:
      - "5432:5432"

openresty

基于 laravel 的写法,主要注意点在于 fastcgi 使用 sock 的方式,对提高 php 性能很有帮助。

server {
    listen       80;

    access_log off;
    error_log off;

    root         /var/www/html/public;

    location = / {
        fastcgi_pass                               unix:/sock/www.sock;
        fastcgi_index                              index.php;
        include                                    fastcgi.conf;
    }

    location = /_status {
        fastcgi_pass                               unix:/sock/www.sock;
        include                                    fastcgi.conf;
        fastcgi_param           SCRIPT_NAME        /_status;
    }

    location / {
        # URLs to attempt, including pretty ones.
        try_files   $uri $uri/ /index.php?$query_string;
    }

    # Remove trailing slash to please routing system.
    if (!-d $request_filename) {
        rewrite     ^/(.+)/$ /$1 permanent;
    }

    location ~* ^(.+\.php)(.*)$ {
        # limit_req zone=req_perip burst=8;
        fastcgi_pass                               unix:/sock/www.sock;
        fastcgi_split_path_info                    ^(.+\.php)(.*)$;
        include                                    fastcgi.conf;
    }

    location /nginx_status {
       stub_status on;
       access_log off;
    }
}

php-fpm

我使用的是 postgresql 数据库,官方默认没有带有 postgresql 的扩展,需要自行编译。官方专门为容器提供了三个的命令,用来简化扩展的安装: docker-php-ext-configuredocker-php-ext-install, 和 docker-php-ext-enable 。具体使用可以查看 Dockerfile:

FROM php:7.1-fpm

RUN apt-get update

RUN apt-get install -y libpq-dev \
    && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \
    && docker-php-ext-install pdo_pgsql pgsql


1 2 3 4 5 72 73 74 75 76