如何使用Docker,Nginx和Letencrypt为甜蜜的HTTPS设置您的网站

by Russell Hammett Jr. (Kritner)

小罗素·哈米特(Kritner)

如何使用Docker,Nginx和Letencrypt为甜蜜的HTTPS设置您的网站 (How to setup your website for that sweet, sweet HTTPS with Docker, Nginx, and letsencrypt)

I’ve used letsencrypt in the past for free certs. I have not successfully utilized it since moving over to docker/kestrel/nginx. That all changed today, and I had a hell of a time figuring out what I was doing to get it working.

过去,我曾使用过letsencrypt获得免费证书。 自转移到docker / kestrel / nginx以来,我还没有成功利用它。 今天这一切都变了,我真费劲地弄清楚我正在做些什么来使其工作。

This whole Unix, docker, nginx, stuff is pretty new (to me), so maybe it’s just something simple I was missing the whole time. Nonetheless, I’m hoping this will help someone else, or me several months down the road if I decide to do it again.

整个Unix,docker,nginx等东西(对我而言)都是很新的,所以也许这只是我一直以来所缺少的简单东西。 但是,我希望这会对其他人有所帮助,或者如果我决定再次这样做的话,我会在几个月后得到帮助。

原始设定 (Original Setup)

I have a .net core website, being hosted via kestrel, running on docker, with a reverse proxy via nginx. Up until now, that reverse proxying from nginx was only working over http/port 80. I don’t know a whole lot about reverse proxies. From the sound of it, it can take in requests, and forward them to a specific location on behalf of the requester. In my case, the nginx container receives http requests, and nginx forwards that request onto my kestrel hosted .net core site. Is that right? Hopefully!

我有一个.net核心网站,该网站通过kestrel托管,在docker上运行,并通过nginx提供反向代理。 到目前为止,nginx的反向代理只能在http / port 80上运行。我对反向代理一无所知。 从它的声音来看,它可以接受请求,并代表请求者将其转发到特定位置。 就我而言,nginx容器接收http请求,然后nginx将请求转发到我的红est托管的.net核心站点上。 那正确吗? 希望!

As mentioned previously, the nginx was only working with http traffic. I was having a lot of trouble getting it working with https, the original configuration is as follows:

如前所述,nginx仅适用于http流量。 我在使用https时遇到很多麻烦,原始配置如下:

docker-compose:

码头工人组成:

version: '3.6'services:    kritner-website-web:    image: ${DOCKER_REGISTRY}/kritnerwebsite    expose:      - "5000"    networks:      - frontend    restart: always    container_name: kritnerwebsite_web  kritner-website-nginx:    image: nginx:latest    ports:      - "80:80"    volumes:      - ../src/nginx/nginx.conf:/etc/nginx/nginx.conf    depends_on:      - kritner-website-web    networks:      - frontend    restart: always    container_name: kritnerwebsite_nginx
networks:  frontend:

In the docker-compose file, I’m using two separate containers — the website, which exposes port 5000 (on the docker network, not publicly), and nginx which operates on port 80.

在docker-compose文件中,我使用了两个单独的容器-网站(暴露docker端口5000(在docker网络上,而不是公开地))和nginx(在端口80上运行)。

nginx.conf

nginx.conf

worker_processes 4; events { worker_connections 1024; } http {    sendfile on;     upstream app_servers {        server kritner-website-web:5000;    }     server {        listen 80;         location / {            proxy_pass         http://app_servers;            proxy_redirect     off;            proxy_set_header   Host $host;            proxy_set_header   X-Real-IP $remote_addr;            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;            proxy_set_header   X-Forwarded-Host $server_name;        }    }}

In the config file, we’re setting up an upstream server with the same name that we’re calling our container service from the docker-compose file kritner-website-web:5000.

在配置文件中,我们将设置一个上游服务器,其名称与从kritner-website-web:5000 compose文件kritner-website-web:5000调用容器服务的名称相同。

Note, all the above can be found at this commit point on my website’s repository.

注意,以上所有内容都可以在我的网站存储库中的此提交点找到。

输入HTTPS (Enter HTTPS)

Letsencrypt is a certificate authority that offers free certs to help secure your website. Why is HTTPS via TLS important? Well, there’s a whole lot to that, and how it works. The basic idea is the user’s traffic is encrypted on either end prior to being sent to the other end. This means if you’re on public wifi, and on https, someone that was “sniffing the wire” so to speak, would see that traffic is occurring, but not the content of said traffic. Since both ends are encrypting/decrypting said traffic with the same encryption key.

Letsencrypt是一个证书颁发机构,它提供免费证书来帮助保护您的网站。 为什么通过TLS的HTTPS如此重要? 好吧,还有很多,以及它是如何工作的。 基本思想是在将用户流量在发送到另一端之前在任一端进行加密。 这意味着,如果您使用的是公共wifi,并且使用https,那么可以说正在“嗅探网络”的人会看到正在发生流量,但不会看到该流量的内容。 由于两端都使用相同的加密密钥对上述流量进行加密/解密。

If you were on an http site, this traffic would be sent back and forth in plain text. Meaning your data is in danger of being eavesdropped on! Maybe I’ll write a bit more about encryption at some point. (*note to self*) Especially since it’s something I’m doing as my day job!

如果您在http网站上,则此流量将以纯文本格式来回发送。 这意味着您的数据有被窃听的危险! 也许我会在某个时候写更多有关加密的内容。 (*注意自我*)尤其是因为这是我日常工作!

letsencrypt is a service I’ve used before. There are various implementations to try to make it as easy as possible to use. Through research for this post, I happened upon this.

letsencrypt是我以前使用过的服务。 有多种实现方式试图使其尽可能地易于使用。 通过对这篇文章的研究,我偶然发现了这一点

Although I hadn’t found this page until now, it would have been useful prior to beginning my adventure. I wanted to use letsencrypt along with my docker container website, and nginx, with as little maintenance as possible. letsencrypt certificates are only good for 90 days.

尽管到目前为止我还没有找到此页面,但是在开始冒险之前它会很有用。 我想将letencrypt与我的docker容器网站和nginx一起使用,并且维护尽可能少。 letsencrypt证书仅可使用90天。

In my research, I happened upon a docker image linuxserver/letsencrypt that promises to utilize nginx, letsencrypt certificate generation, AND auto renewal. Sounds awesome! While the documentation of the image seems mostly adequate — for someone well versed in all this process. I found it to be lacking. The whole setup process took me some time to figure out. Hence this post, to hopefully help out the next person, or again me in the future!

在我的研究中,我偶然遇到了一个码头映像linuxserver / letsencrypt ,该映像承诺利用nginx,letencrypt证书生成和自动续订。 听起来太酷了! 尽管图像的文档似乎大多数都足够了,但是对于那些精通所有这些过程的人来说。 我发现它缺少。 整个设置过程花了我一些时间弄清楚。 因此,这篇文章希望能帮助下一个人,或者将来帮助我!

奋斗 (Struggles)

The things I most struggled with when getting this linuxserver/letsencrypt image up and working were:

在启动并运行linuxserver / letsencrypt映像时,我最努力的事情是:

  • How docker volumes “work” and their relationship with this container

    码头工人卷如何“工作”及其与该容器的关系
  • How to set volumes up to utilize my configuration (related to the above point) — I was initially having a lot of trouble figuring out why my settings changed on the container were being changed back on reloading of said container (because that’s what they’re supposed to do)

    如何设置卷以利用我的配置(与上述要点有关)—我最初在弄清楚为什么我在容器上更改的设置在重新加载所述容器时又被更改了时遇到了很多麻烦(因为这就是它们的含义)应该做的)
  • How to set up the correct nginx configuration — where to put it, and what to put in it.

    如何设置正确的nginx配置-放置在何处以及放置在其中的内容。
Docker卷 (Docker volumes)

Docker volumes (doc):

Docker卷( doc ):

Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. While bind mounts are dependent on the directory structure of the host machine, volumes are completely managed by Docker. Volumes have several advantages over bind mounts

卷是用于持久化由Docker容器生成和使用的数据的首选机制。 尽管绑定挂载取决于主机的目录结构,但是卷完全由Docker管理。 与绑定安装相比,卷具有多个优点

letsencrypt has a lot of configuration to go along with it. It took a while for me to realize, but I needed a volume that mapped from a directory on the docker host to a specific directory on the letsencrypt image. I eventually accomplished this in the compose file like so:

letsencrypt具有许多配置。 我花了一段时间才意识到,但是我需要一个从Docker 主机上的目录映射到letencrypt映像上特定目录的卷。 我最终在compose文件中完成了如下操作:

volumes:      - ${DOCKER_KRITNER_NGINX}:/config       - ./nginx.conf:/config/nginx/site-confs/default

The first item in the array (${DOCKER_KRITNER_NGINX}:/config) takes a new environment variable that maps the host directory (defined in the variable) to the /config within the docker container itself. This means that the docker host (at the env var path) will contain the same config as the docker container at the secondary portion of the volume mapping (/config)

数组中的第一项( ${DOCKER_KRITNER_NGINX}:/config )使用一个新的环境变量,该变量将主机目录(在变量中定义)映射到${DOCKER_KRITNER_NGINX}:/config容器本身内的/config 。 这意味着docker主机 (在env var路径)将在卷映射的第二部分( /config )包含与docker容器相同的配置。

The second item (./nginx.conf:/config/nginx/site-confs/default) maps my local repositories nginx.conf file (the file where I set up the reverse proxy) to override the /config/nginx/site-confs/default file on the docker host and container.

第二项( ./nginx.conf:/config/nginx/site-confs/default )映射我的本地存储库nginx.conf文件(我在其中设置反向代理的文件)以覆盖/config/nginx/site-confs/default主机和容器上的/config/nginx/site-confs/default文件。

The full list of files that I ended up needing to modify for my particular situation was:

我针对特定情况最终需要修改的文件的完整列表为:

  • /config/dns-conf/dnsimple.ini

    /config/dns-conf/dnsimple.ini

  • /config/nginx/site-confs/default

    /config/nginx/site-confs/default

The dnsimple.ini configuration was add my api key, and the …/default houses the nginx configuration.

dnsimple.ini配置已添加我的api密钥,并且…/default包含nginx配置。

The final default configuration I ended up with is:

我最终得到的最终default配置是:

upstream app_servers {        server kritnerwebsite:5000;}
## Version 2018/09/12 - Changelog: https://github.com/linuxserver/docker-letsencrypt/commits/master/root/defaults/default
# listening on port 80 disabled by default, remove the "#" signs to enable# redirect all traffic to httpsserver { listen 80; server_name kritnerwebsite; return 301 https://$host$request_uri;}
# main server blockserver { listen 443 ssl;
# enable subfolder method reverse proxy confs include /config/nginx/proxy-confs/*.subfolder.conf;
# all ssl related config moved to ssl.conf include /config/nginx/ssl.conf;  # enable for ldap auth #include /config/nginx/ldap.conf;
client_max_body_size 0;
location / {            proxy_pass         http://app_servers;            proxy_redirect     off;            proxy_set_header   Host $host;            proxy_set_header   X-Real-IP $remote_addr;            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;            proxy_set_header   X-Forwarded-Host $server_name;    }
}
# enable subdomain method reverse proxy confsinclude /config/nginx/proxy-confs/*.subdomain.conf;# enable proxy cache for authproxy_cache_path cache/ keys_zone=auth_cache:10m;

There are a few changes from the default that was there, which I’ll try to highlight next.

与那里的默认设置相比,有一些更改,接下来我将着重介绍这些更改。

upstream app_servers {        server kritnerwebsite:5000;}

Above is pretty cool, since docker has its own internal DNS (I guess?). You can set up an upstream server by the containers name, in my case “kritnerwebsite”. (Note: I changed it from earlier in the post, which was “kritner-website-web”.)

上面的代码很酷,因为docker有自己的内部DNS(我想呢?)。 您可以通过容器名称(在本例中为“ kritnerwebsite”)设置上游服务器。 (注意:我从帖子的前面的“ kritner-website-web”更改了它。)

# listening on port 80 disabled by default, remove the "#" signs to enable# redirect all traffic to httpsserver { listen 80; server_name kritnerwebsite; return 301 https://$host$request_uri;}

Uncommented out this section from the default, applied my server_name of “kritnerwebsite”

取消注释此部分的默认值,应用了我的server_name“ kritnerwebsite”

# main server blockserver { listen 443 ssl;
# enable subfolder method reverse proxy confs include /config/nginx/proxy-confs/*.subfolder.conf;
# all ssl related config moved to ssl.conf include /config/nginx/ssl.conf;  # enable for ldap auth #include /config/nginx/ldap.conf;
client_max_body_size 0;
location / {            proxy_pass         http://app_servers;            proxy_redirect     off;            proxy_set_header   Host $host;            proxy_set_header   X-Real-IP $remote_addr;            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;            proxy_set_header   X-Forwarded-Host $server_name;    }
}

In the above, it’s mostly from the “default” save for “location” and everything within that object. Here, we’re setting up the reverse proxy to forward requests to “/” (anything) to our http://app_servers (kritnerwebsite as per our upstream).

在上面,它主要来自“位置”的默认值以及该对象中的所有内容。 在这里,我们正在设置反向代理,以将对“ /”(任何内容)的请求转发到我们的http://app_servers (根据上游的kritnerwebsite)。

docker-compose.yml (docker-compose.yml)

Our docker compose file didn’t change a *whole* lot from the initial. There were a few notable changes, which I’ll also get into describing:

我们的docker compose文件与初始文件相比并没有改变*整体*。 有一些值得注意的更改,我还将介绍这些更改:

version: '3.6'services:    nginx:    image: linuxserver/letsencrypt    ports:      - "80:80"      - "443:443"    volumes:      - ${DOCKER_KRITNER_NGINX}:/config       - ./nginx.conf:/config/nginx/site-confs/default    depends_on:      - kritnerwebsite    networks:      - frontend    container_name: nginx    environment:      - PUID=1001 # get on dockerhost through command "id <user>""      - PGID=1001      - EMAIL=kritner@gmail.com      - URL=kritner.com      - SUBDOMAINS=www      - TZ=America/NewYork      - VALIDATION=dns # using dns validation      - DNSPLUGIN=dnsimple # via dnsimple, note there is additional configuration require separate from this file      # - STAGING=true # this should be uncommented when testing for initial success, to avoid some rate limiting
kritnerwebsite:    image: ${DOCKER_REGISTRY}/kritnerwebsite    networks:      - frontend    expose:      - "5000"    restart: always    container_name: kritnerwebsite  networks:  frontend:

for the new parts:

对于新零件:

nginx:    image: linuxserver/letsencrypt

Using a different image — linuxserver/letsencrypt instead of nginx. This image has nginx included, but also certbot, along with a cronjob to run certbot at application start.

使用不同的映像-linuxserver / letsencrypt代替nginx。 该映像不仅包括nginx,还包括certbot,以及在应用程序启动时运行certbot的cronjob。

ports:      - "80:80"      - "443:443"

Now we’re using both http and https ports (though note, we’re redirecting http calls to https via the nginx config).

现在,我们同时使用http和https端口(不过请注意,我们正在通过nginx配置将http调用重定向到https)。

volumes:      - ${DOCKER_KRITNER_NGINX}:/config       - ./nginx.conf:/config/nginx/site-confs/default

Already discussed earlier in the post, we’re using these volumes to properly set up the nginx configuration, with our dnsimple api key, as well as our reverse proxying to the kritnerwebsite.

文章前面已经讨论过,我们正在使用这些卷通过dnsimple api密钥以及对kritnerwebsite的反向代理来正确设置nginx配置。

environment:      - PUID=1001 # get on dockerhost through command "id <user>"      - PGID=1001      - EMAIL=kritner@gmail.com      - URL=kritner.com      - SUBDOMAINS=www      - TZ=America/NewYork      - VALIDATION=dns # using dns validation      - DNSPLUGIN=dnsimple # via dnsimple, note there is additional configuration require separate from this file      # - STAGING=true # this should be uncommented when testing for initial success, to avoid some rate limiting

Environment variables needed as per the letsencrypt documentation can be found here.

需要为每letsencrypt文档的环境变量可以找到这里

  • PUID/PGID — get on dockerhost through command “id <user>”

    PUID / PGID —通过命令“ id <user>”进入dockerhost
  • Email — well, your email (used for cert expiration emails apparently)

    电子邮件-好吧,您的电子邮件(显然用于证书过期电子邮件)
  • URL — the main domain URL

    URL-主域URL
  • subdomains — any subdomains to the URL to be certified

    子域-要认证的URL的任何子域
  • TZ — timezone

    TZ —时区
  • Validation — the type of validation to do — I’m using DNSimple, so i needed DNS in this field. Other options are html, tls-sni

    验证-要做的验证类型-我使用的是DNSimple,因此我需要在此字段中使用DNS。 其他选项是html,tls-sni
  • dnsplugin — dnsimple — other options are cloudflare, cloudxns, digitalocean, dnsmadeeasy, google, luadns, nsone, rfc2136 and route53 as per the letsencrypt documentation

    dnsplugin — dnsimple —根据cloudflare ,其他选项是cloudflarecloudxnsdigitaloceandnsmadeeasygoogleluadnsnsonerfc2136route53

  • Staging=true — I used this for testing out all my various attempts prior to getting it working. letsencrypt has rate limiting when not running in staging mode (or at least in staging it’s harder to run up against).

    Staging = true-在使它工作之前,我用它来测试所有尝试。 当不以暂存模式运行时(或至少在暂存模式下,它很难运行),letsencrypt具有速率限制。

All the above changes, experimenting, failing, and then finally succeeding can be found in this pull request.

以上所有更改(尝试,失败然后最终成功)都可以在此pull request中找到。

The final result?

最终结果?

and from https://www.ssllabs.com/

并来自https://www.ssllabs.com/-

Not an “A+”, but really not bad for using one pre-built docker image for my HTTPs needs!

不是“ A +”,但对于我的HTTP使用一个预先构建的docker镜像确实不错!

Related:

有关:

翻译自: https://www.freecodecamp.org/news/docker-compose-nginx-and-letsencrypt-setting-up-website-to-do-all-the-things-for-that-https-7cb0bf774b7e/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值