Cloud Native应用交付

  • 首页
  • 关于本站
  • 个人介绍
  • Downloads
  • Repo
    • Github
    • Container
  • F5
    • F5 In AI Agent Arch
    • F5 AI Infrastructure Blueprint
    • F5 Python SDK
    • F5-container
    • F5-LBaaS
  • 社交
    • 联系我
    • 微信/微博
    • 公众号
    • 打赏赞助
行至水穷处 坐看云起时
Cloud Native Application Services: cnadn.net
  1. 首页
  2. 容器/k8s
  3. 正文

博客Docker化实践

2017年07月28日 12137点热度 5人点赞 0条评论

Warning: Array to string conversion in /home/wwwroot/myf5/wp-content/plugins/wpjam-basic/public/wpjam-utils.php on line 496

在写这篇博客的时候,系统已经稳定运行在docker容器上。本着折腾的精神,觉的还是应该将博客进行docker化,一来毕竟在内存上多花了不少钱,不充分利用一下有点说不不过去,最重要的是如果docker化,以后万一需要迁移博客到别的主机上,我只需要将相关容器打包一下拷贝过去起来就行了,简单快速。

这也是我第一次实践docker化工作,从小心谨慎以及可回退角度,做了以下目标设定:

  1. 将现有的所有服务docker化,包含 nginx,php-fpm,memcached,mysql

  2. docker化工作不能影响现有底层系统上的已有lnmp服务的配置,因为现有配置中有不少配置是会定期动态变化的,所以不能因为docker化改变现有的结构、配置等。同时要做到万一不用docker直接本地启动原来服务即可。 (这个需求其实埋下很多坑)

  3. docker化后ssllabs评分不能降低,必须还是A+

为了实现上述目标,直接pull一个现成的官方 nginx,官方php,甚至官方wordpress是不可行的,需要创建一个自己的容器来实现ct-transparency,brotli, dynamic-tls-record-sizing,以及openssl需要打上chacha20的patch。而为了简化工作,决定将php和nginx放到一个容器里。

[title]Nginx-php容器化[/title]

在PHP官方的5.6.31-fpm-alphine镜像基础上补充编译nginx,并为php增加memached扩展支持。以下dockerfile在docker hub和阿里云docker镜像站上以及本地均build通过。在实际dockerfile制作过程遇到了不少问题,总结下来主要有:

  1. 为了兼容原来nginx配置环境的,需要仔细考虑编译过程中相关配置目录的规划以及相关目录的提前创建,防止在mount目录给容器后,导致原来的配置提示找不到相关引用文件,在这一点上经历了多次修改和重编译,踩了不少坑
  2. centos 7.3上如果docker的storage driver是 overlay方式,且linux本身是xfs格式系统+ftype=1,则可能会出现build时候无法rm -rf命令无法删除目录情况,这是由于centos的bug,参考https://github.com/docker/docker/issues/31717
    我是将docker启动的storage driver改为devicemapper方式来解决
  3. 其它因素,参考了不少别人的dockerfile,certificate transparency编译用的包的下载地址引用的是github上一个人的,但这个人突然有一天删除了那个文件,上一次build还通过了,下次build就因为无法下载失败了。。还好我有提前本地备份,索性将那几个需要的文件都改为在自己的github上提供
  4. 国内build有可能还会遇到dns无法解析问题,其实明明是正常的,比如在阿里云国内节点编译则会失败,选择阿里云境外节点则顺利完成
  5. 由于是nginx+php在同一个容器里需要同时暴露服务,这与容器本来的设计思想有些违背,所以使用了supervisord来实现前台启动双服务,需要注意的是supervisord里一样不能对nginx以daemon方式启动,否则supervisor会不断的提示nginx启动失败并重启
FROM php:5.6.31-fpm-alpine
#FROM alpine:3.6

MAINTAINER Jing Lin <web@myf5.net>

ENV NGINX_VERSION 1.12.1
ENV OPENSSL_VERSION 1.0.2l
ENV OPENSSL_CHACHA https://raw.githubusercontent.com/cloudflare/sslconfig/master/patches/openssl__chacha20_poly1305_draft_and_rfc_ossl102j.patch
ENV NGX_VERSION_TRANSPARENCY=1.3.2
ENV NGX_VERSION_BROTLI=1.0.2

ENV php_conf /usr/local/etc/php-fpm.conf
ENV fpm_conf /usr/local/etc/php-fpm.d/www.conf
ENV php_vars /usr/local/etc/php/conf.d/docker-vars.ini

###################################
# OPENSSL                         #
###################################

RUN	apk add --no-cache --virtual .build-deps \
		gcc \
		libc-dev \
		make \
		pcre-dev \
		zlib-dev \
		linux-headers \
		curl \
		gnupg \
		libxslt-dev \
		gd-dev \
		geoip-dev \
		perl-dev \
		wget \
		ca-certificates \
		g++ \
		zip \
	&& mkdir -p /usr/src \
	&& wget https://openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz \
	&& tar zxvf openssl-$OPENSSL_VERSION.tar.gz -C /usr/src \
	&& rm openssl-$OPENSSL_VERSION.tar.gz \
	&& wget -O /usr/src/chacha.patch $OPENSSL_CHACHA \
	&& cd /usr/src/openssl-$OPENSSL_VERSION \
	&& patch -p1 < ../chacha.patch \
	&& ./config \
	&& make depend
	
###################################
# CERTIFICATE TRANSPARENCY        #
###################################

COPY nginx-ct-1.3.2.zip /tmp/
RUN unzip /tmp/nginx-ct-1.3.2.zip -d /usr/src \
	&& rm /tmp/nginx-ct-1.3.2.zip \
	&& echo "CT copyed and unzipped"

###################################
# GOOGLE BROTLI      			  #
###################################

COPY ngx_brotli-1.0.2.zip /tmp/
RUN unzip /tmp/ngx_brotli-1.0.2.zip -d /usr/src \
	&& rm /tmp/ngx_brotli-1.0.2.zip \
	&& echo "BROTILI copyed and unzipped"

###################################
# TLS Dynamic Reord Sizing		  #
# Patch for NGINX      			  #
###################################

RUN wget -O /usr/src/nginx-dynamic_tls.patch https://raw.githubusercontent.com/cloudflare/sslconfig/master/patches/nginx__1.11.5_dynamic_tls_records.patch \
	&& echo "TLS Dynamic Reord Sizing patch downloaded"



###################################
# NGINX                           #
###################################
		
ENV GPG_KEYS B0F4253373F8F6F510D42178520A9993A1C052F8
ENV CONFIG "\
	--prefix=/usr/local/nginx \
	--sbin-path=/usr/sbin/nginx \
	--modules-path=/usr/lib/nginx/modules \
	--conf-path=/usr/local/nginx/conf/nginx.conf \
	--error-log-path=/var/log/nginx/error.log \
	--http-log-path=/var/log/nginx/access.log \
	--pid-path=/var/run/nginx.pid \
	--lock-path=/var/run/nginx.lock \
	--http-client-body-temp-path=/var/cache/nginx/client_temp \
	--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
	--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
	--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
	--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
	--user=www \
	--group=www \
	--with-http_ssl_module \
	--with-http_realip_module \
	--with-http_addition_module \
	--with-http_sub_module \
	--with-http_dav_module \
	--with-http_flv_module \
	--with-http_mp4_module \
	--with-http_gunzip_module \
	--with-http_gzip_static_module \
	--with-http_random_index_module \
	--with-http_secure_link_module \
	--with-http_stub_status_module \
	--with-http_auth_request_module \
	--with-http_xslt_module=dynamic \
	--with-http_image_filter_module=dynamic \
	--with-http_geoip_module=dynamic \
	--with-http_perl_module=dynamic \
	--with-threads \
	--with-stream \
	--with-stream_ssl_module \
	--with-http_slice_module \
	--with-mail \
	--with-mail_ssl_module \
	--with-stream_ssl_preread_module \
    --with-stream_realip_module \
    --with-stream_geoip_module=dynamic \
	--with-file-aio \
	--with-http_v2_module \
	--with-compat \
	--with-openssl=/usr/src/openssl-$OPENSSL_VERSION \
	--add-module=/usr/src/nginx-ct-${NGX_VERSION_TRANSPARENCY} \
	--add-module=/usr/src/ngx_brotli-${NGX_VERSION_BROTLI} \
	"

RUN \
	addgroup -S www \
	&& adduser -D -S -h /var/cache/www -s /sbin/nologin -G www www \
	&& curl -fSL http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz -o nginx.tar.gz \
	&& curl -fSL http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz.asc  -o nginx.tar.gz.asc \
	&& export GNUPGHOME="$(mktemp -d)" \
	&& gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEYS" \
	&& gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz \
	&& rm -r "$GNUPGHOME" nginx.tar.gz.asc \
	&& tar -zxC /usr/src -f nginx.tar.gz \
	&& rm nginx.tar.gz \
	&& cd /usr/src/nginx-$NGINX_VERSION \
	&& patch -p1 < /usr/src/nginx-dynamic_tls.patch \
	&& echo "Dynamic TLS size recording pathed for nginx" \
	&& ./configure $CONFIG --with-debug \
	&& make \
	&& mv objs/nginx objs/nginx-debug \
	&& mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so \
	&& mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so \
	&& mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so \
	&& mv objs/ngx_http_perl_module.so objs/ngx_http_perl_module-debug.so \
	&& ./configure $CONFIG \
	&& make \
	&& make install \
	&& rm -rf /usr/local/nginx/html/ \
	&& mkdir /usr/local/nginx/vhost/ \
	&& mkdir /usr/local/nginx/ssl/ \
	&& mkdir -p /var/cache/nginx/client_temp \
	&& mkdir -p /var/cache/nginx/proxy_temp \
	&& mkdir -p /var/cache/nginx/fastcgi_temp \
	&& mkdir -p /var/cache/nginx/uwsgi_temp \
	&& mkdir -p /var/cache/nginx/scgi_temp \
	&& mkdir -p /home/wwwlogs/ \
	&& mkdir -p /home/wwwroot/myf5/ \
	&& mkdir -p /etc/letsencrypt/sct/ \
	&& install -m644 html/index.html /home/wwwroot/myf5/ \
	&& install -m644 html/50x.html /home/wwwroot/myf5/ \
	&& install -m755 objs/nginx-debug /usr/sbin/nginx-debug \
	&& install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so \
	&& install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so \
	&& install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so \
	&& install -m755 objs/ngx_http_perl_module-debug.so /usr/lib/nginx/modules/ngx_http_perl_module-debug.so \
	&& ln -s ../../usr/lib/nginx/modules /usr/local/nginx/modules \
	&& strip /usr/sbin/nginx* \
	&& strip /usr/lib/nginx/modules/*.so \
	&& runDeps="$( \
		scanelf --needed --nobanner /usr/sbin/nginx /usr/lib/nginx/modules/*.so \
			| awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \
			| sort -u \
			| xargs -r apk info --installed \
			| sort -u \
	)" \
	&& apk add --virtual .nginx-rundeps $runDeps \
	&& apk del .build-deps \
	&& rm -rf /usr/src/openssl-$OPENSSL_VERSION \
	&& rm -rf /usr/src/nginx-ct-$GX_VERSION_TRANSPARENCY \
	&& rm -rf /usr/src/ngx_brotli-$NGX_VERSION_BROTLI \
	&& rm -rf /usr/src/nginx-dynamic_tls.patch \
	&& rm -rf /usr/src/nginx-$NGINX_VERSION \
	&& apk add --no-cache gettext \
	\
	# forward request and error logs to docker log collector
	&& ln -sf /dev/stdout /var/log/nginx/access.log \
	&& ln -sf /dev/stderr /var/log/nginx/error.log \

# COPY pre defined file, make sure there is correct nginx configuration files, these files are based my own nginx.
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
COPY enable-php.conf /usr/local/nginx/conf/enable-php.conf
COPY fastcgi.conf /usr/local/nginx/conf/fastcgi.conf
COPY wordpress.conf /usr/local/nginx/conf/wordpress.conf
COPY ./vhost/nginx.vh.default.conf /usr/local/nginx/conf/vhost/default.conf
COPY ./ssl/* /usr/local/nginx/conf/ssl/
COPY digicert.sct /etc/letsencrypt/sct/digicert.sct
COPY icarus.sct /etc/letsencrypt/sct/icarus.sct
COPY Shanghai /etc/localtime 



########Start PHP##########
RUN echo @testing 	>> /etc/apk/repositories && \
    echo /etc/apk/respositories && \
    apk update && \
    apk add --no-cache bash \
    openssh-client \
    wget \
    supervisor \
    curl \
    libcurl \
    git \
    python \
    python-dev \
    py-pip \
    augeas-dev \
    openssl-dev \
    ca-certificates \
    dialog \
    gcc \
    musl-dev \
    linux-headers \
    libmcrypt-dev \
    libpng-dev \
    icu-dev \
    libpq \
    libxslt-dev \
    libffi-dev \
    libmemcached-dev \
    cyrus-sasl-dev \
    freetype-dev \
    sqlite-dev \
    libjpeg-turbo-dev && \
    docker-php-ext-configure gd \
      --with-gd \
      --with-freetype-dir=/usr/include/ \
      --with-png-dir=/usr/include/ \
      --with-jpeg-dir=/usr/include/ && \
    #curl iconv session
    curl -L -o /tmp/memcached.tar.gz http://pecl.php.net/get/memcached-2.2.0.tgz &&\
    tar -xzvf /tmp/memcached.tar.gz &&\
    mv memcached-2.2.0 /usr/src/php/ext/memcached &&\
    rm /tmp/memcached.tar.gz &&\
    docker-php-ext-install pdo_mysql pdo_sqlite mysqli mcrypt gd exif intl xsl json soap dom zip opcache memcached && \
    docker-php-source delete && \
    mkdir -p /var/log/supervisor && \
    echo "Asia/Shanghai" >  /etc/timezone &&\
    EXPECTED_COMPOSER_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig) && \
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
    php -r "if (hash_file('SHA384', 'composer-setup.php') === '${EXPECTED_COMPOSER_SIGNATURE}') { echo 'Composer.phar Installer verified'; } else { echo 'Composer.phar Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \
    php composer-setup.php --install-dir=/usr/bin --filename=composer && \
    php -r "unlink('composer-setup.php');"  && \
    #pip install -U pip && \
    #pip install -U certbot && \
    #mkdir -p /etc/letsencrypt/webrootauth && \
    apk del gcc musl-dev linux-headers libffi-dev augeas-dev python-dev &&\
    rm -rf /usr/src


#############3 tweak php-fpm config##################
RUN echo "cgi.fix_pathinfo=0" > ${php_vars} &&\
    echo "upload_max_filesize = 100M"  >> ${php_vars} &&\
    echo "post_max_size = 100M"  >> ${php_vars} &&\
    echo "variables_order = \"EGPCS\""  >> ${php_vars} && \
    echo "memory_limit = 128M"  >> ${php_vars} && \
    sed -i \
        -e "s/;catch_workers_output\s*=\s*yes/catch_workers_output = yes/g" \
        -e "s/pm.max_children = 5/pm.max_children = 20/g" \
        -e "s/pm.start_servers = 2/pm.start_servers = 10/g" \
        -e "s/pm.min_spare_servers = 1/pm.min_spare_servers = 5/g" \
        -e "s/pm.max_spare_servers = 3/pm.max_spare_servers = 20/g" \
        -e "s/;pm.max_requests = 500/pm.max_requests = 200/g" \
        -e "s/user = www-data/user = www/g" \
        -e "s/group = www-data/group = www/g" \
        -e "s/;listen.mode = 0660/listen.mode = 0666/g" \
        -e "s/;listen.owner = www-data/listen.owner = www/g" \
        -e "s/;listen.group = www-data/listen.group = www/g" \
        -e "s/listen = 127.0.0.1:9000/listen = \/tmp\/php-cgi.sock/g" \
        -e "s/^;clear_env = no$/clear_env = no/" \
        ${fpm_conf}

ADD start.sh /start.sh
ADD supervisord.conf /etc/supervisord.conf
RUN chmod 755 /start.sh

EXPOSE 80/tcp 443/tcp
CMD ["/start.sh"]

镜像制作的一点心得:尽可能的简化需求,力争实现容器本身是一个完整的个体,如果为了所谓的灵活导致过多的考虑外部数据的关联,会使得容器与外部环境耦合性太强,失去了容器本身的意义。但同时又要综合衡量容器化后,内外文件交互的必要性,找到一个灵活的平衡点。起初我是抱着一个容器打天下的思路去看别人的dockerfile,寄希望随便拿一个可以满足自己环境要求的dockerfile来编译,但看了大量dockerfile后发现每个人共享出来的dockerfile其实都是最适合他自己环境的,多多少都会有一些为自己环境定制的东西,所以docker镜像除非标准的官方通用镜像,否则真的是千人千面。正如我build的这个,如果你愿意,可以直接从github上取下并build,build完毕后可以启动使用,但是相关配置、乃至为了适应配置所用的临时证书等都不是通用的。

build后的镜像启动后,别看到启动成功了就认为成功了,一定要 docker logs去仔细看下

[title]启动镜像[/title]

镜像在docker hub以及阿里云上通过拉取github来直接build,由于主机在阿里云上,所以拉取的时候直接从阿里云的docker镜像站拉取就行了。每个人都可以使用阿里云的docker镜像加速,如果自己本地测试也不防将register改为阿里云的,具体方法https://cr.console.aliyun.com登录后查看,每个人都可以得到一个专有的加速连接。

拉取到本地后,重新docker tag一下,不然阿里的仓库名称太长了。随后执行
docker run -itd -v /***/nginx/:/***/nginx/ -v /etc****:/etc/*** -v /***/wwwroot/:/***/wwwroot/:rw --name nginx -p 80:80 -p 443:443 myf5nginx

上述命令里隐去了一些路径。

容器成功启动:

CONTAINER                  ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                NAMES
d35958152c86        mynginx             "docker-php-entryp..."   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 9000/tcp   nginx

启动后,首先会发现提示无法连接数据库,因为相关数据库连接配置是使用的localhost且相关权限是只容许本地访问,所以需要对mysql连接即相关数据库用户权限做下改造。

随后可以访问,但是访问网站很慢。这是由于博客启用了memcached,且是通过127.0.0.1来连接的,容器本身内部是没有memecached服务的,所以导致慢,暂时先停掉memcache 功能。

此时博客可以正常访问,而且感觉速度和以前一样。进入博客后台,提示有插件更新,于是更新插件,但是系统提示无权限,看来文件权限属性有了问题,进入容器内看下文件是啥权限:

uid,gid都是1001. 这个1001其实是宿主机本地的某用户的ID,在mount给容器后,容器内运行nginx/php的那个用户并不是这个id而是100,所以php提示无权更新文件。此时需要将容器的那个用户的uid改为1001即可,方法可以是:
1. 在容器内使用usermod去修改那个用户的uid,但是由于是alpine的基础镜像,usermod命令是不存在的,所以不可行

2. build容器的时候,就提前修改好和宿主机一致,这同样需要在容器里增加相关命令安装,但是修改出来的镜像很可能在放到别的宿主机上后,因为别的宿主机上同名用户的uid又不一样了而导致问题

3. 我是比较暴力的将宿主机上的该用户uid改成容器里的100,然后给目录重新chown,这样mount上去的文件就是100了,从而容器用户可以有权限

4. 启动容器时候使用特权参数,这个方法我没测试

由于这方面实践经验较少,不知道在一个复杂的大型生产环境里是如何有效解决这个问题的。从上面可以看出,其实要想实现一个镜像跑遍所有服务器,还不是那么容易的。

解决上述问题后,博客运行完全正常了,ssllabs跑分依旧是A+

[title]mysql容器化[/title]

由于我的mysql没使用innodb,因此我直接将原来本地mysql所用的data目录直接mount给容器使用,这样设置后容器里的mysql确实可以读取到数据库,但是在宿主机查看这个目录时候发现文件用户被设置成了systemd-bus-proxy:input的名称,显然容器用其用户id覆盖了文件权限,这样会影响本地myql未来启动使用这些数据库文件,所以为了保险起见,决定mount一个独立空文件夹给容器,然后做一次标准的mysql数据库文件导入导出工作。这样mysql容器里变拥有了最新的网站数据。然后nginx容器使用link方式连接容器,并设置WP相关数据库server配置为link的别名。

这里无需将mysql暴露给宿主机,因为宿主机用不到,需要注意如果使用-p参数暴露了端口给宿主机,docker自己会自动增加一个iptables规则,这个规则可能会导致内部容器无法连接宿主机IP:port。

docker run --name mysql -v /***/dockerdata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=mysqlpassword -d mysql:tag

[title]memcached容器化[/title]

使用官方的memcached镜像启动,nginx-php容器启动时候link过去。根据WP的memcached插件提示在WP配置文件里增加自定义memcached server的配置,使用link时候设置的别名即可,例如memcached:11211

WordPress Memcached Status
Using the PHP Memcached class to interact with Memcached


memcached: memcached:11211
pid: 1
uptime: 901
threads: 4
time: 1501245716
pointer_size: 64
rusage_user_seconds: 0
rusage_user_microseconds: 185891
rusage_system_seconds: 0
rusage_system_microseconds: 201686
curr_items: 912
total_items: 995
limit_maxbytes: 67108864
curr_connections: 10
total_connections: 81
connection_structures: 12
bytes: 816153
cmd_get: 2473
cmd_set: 1172
get_hits: 1718
get_misses: 755
evictions: 0
bytes_read: 1360313
bytes_written: 4427476
version: 1.5.0
docker run -itd --name mymemcached memcached -m 64

最终Nginx容器的run命令是:

docker run -itd -v /***/nginx/:/***/nginx/ -v /***/letsencrypt:/***/letsencrypt/ -v /***/www/:/***/www/:rw --name nginx --link=mymemcached:memcached --link=mysql:mysql -p 80:80 -p 443:443 mynginx

[title]Docker Compose管理所有容器[/title]

除了上述手工运行命令逐个容器启动外,还可以利用docker-compose来实现统一启动和管理,有点类似kubernetes的deployment。保存以下文件为docker-compose.yml, 然后在同目录下执行 docker-compose up -d 启动所有服务

version: "3"
services:
  mysql:
    image: mysql:5.7.18
    container_name: mysql
    volumes:
       - /***/dockerdata:/***/mysqldata
    environment:
       - MYSQL_ROOT_PASSWORD=****

  memcached:
    image: memcached
    container_name: mymemcached
    command: ["-m", "64"]


  nginx:
    image: mynginx
    container_name: nginx
    volumes:
      - /****/nginx/:/***/nginx/
      - /etc/letsencrypt:/etc/letsencrypt/
      - /***/root/:/***/oot/:rw 
    depends_on:
      - mysql
      - memcached
    links:
      - mysql:mysql
      - memcached:memcached
    ports:
      - 80:80
      - 443:443

其它处理,修改letsencrypt相关脚本适应容器化后的nginx配置加载

<EOF>

实践过程中参考了:

https://hub.docker.com/r/panascais/nginx/

https://hub.docker.com/r/frostiede/nginx/~/dockerfile/

https://github.com/ngineered/nginx-php-fpm/blob/master/Dockerfile

https://xlange.com/post/dockerfile-baseon-official-php-image.html

如果对此感兴趣,此文相关dockerfile及文件放置在github上:https://github.com/myf5/nginx-php-fpm

hub上镜像文件: https://hub.docker.com/r/myf5/

扫描二维码关注本博公众号:

微信公众号

微信公众号

Array
本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: docker docker-compose nginx php wordpress
最后更新:2020年05月21日

纳米

linjing.io

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

页面AI聊天助手

纳米

linjing.io

☁️迈向Cloud Native ADC ☁️

认证获得:
TOGAF: ID 152743
Kubernetes: CKA #664
Microsoft: MCSE MCDBA
Cisco: CCNP
Juniper: JNCIS
F5:
F5 Certified Solution Expert, Security
F5 Certified Technology Specialist, LTM/GTM/APM/ASM
F5 Certified BIG-IP Administrator
  • 点击查看本博技术要素列表
  • 归档
    分类
    • AI
    • Automation
    • Avi Networks
    • Cisco ACI
    • CISCO资源
    • F5 with ELK
    • F5-Tech tips
    • F5技术
    • Juniper
    • Linux
    • NGINX
    • SDN
    • ServiceMesh
    • WEB编程
    • WINDOWS相关
    • 业界文章
    • 交换机技术
    • 化云为雨/Openstack
    • 协议原理
    • 容器/k8s
    • 我的工作
    • 我的生活
    • 网站技术
    • 路由器技术
    • 项目案例
    标签聚合
    istio neutron openstack F5 docker k8s bigip api envoy gtm DNS network nginx irule flannel
    最近评论
    纳米 发布于 2 天前(11月08日) 这文件是独立密码,需要的联系
    纳米 发布于 2 天前(11月08日) 这几个是独立密码。需要的话联系。
    Abeny 发布于 9 个月前(02月20日) Very good!
    李成才 发布于 1 年前(06月03日) 大佬公众号里查的下载密码都不对呢
    李成才 发布于 2 年前(04月09日) 大佬,F5排错培训材料,ssl培训这几个新的材料下载密码不对呢,已关注公众号获取下载密码
    浏览次数
    • Downloads - 197,821 views
    • 联系我 - 138,930 views
    • 迄今为止最全最深入的BIGIP-DNS/GTM原理及培训资料 - 129,287 views
    • Github - 116,050 views
    • Sniffer Pro 4 70 530抓包软件 中文版+视频教程 - 93,319 views
    • 迄今为止最全最深入的BIGIP-DNS/GTM原理及培训资料 - 91,400 views
    • F5常见log日志解释 - 91,172 views
    • 从传统ADC迈向CLOUD NATIVE ADC - 下载 - 89,311 views
    • 关于本站 - 78,000 views
    • F5利用Elastic stack(ELK)进行应用数据挖掘系列(2)-DNS - 65,610 views
    链接表
    • F5SE创新
    • Jimmy Song‘s Blog
    • SDNlab
    • Service Mesh社区
    • 三斗室
    • 个人profile
    • 云原生社区

    COPYRIGHT © 2023 Cloud Native 应用交付. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    京ICP备14048088号-1

    京公网安备 11010502041506号