使用docker compose进行本地https开发

为什么在开发中使用HTTPS? (Why using HTTPS in development ?)

The need to use HTTPS in development may seem anecdotal, however, several cases meet this need:

在开发中使用HTTPS的需求似乎很有趣,但是,有几种情况可以满足此需求:

  • To perform certain tests locally (such as lighthouse audits)

    在本地执行某些测试(例如灯塔审核)

  • Avoid CORS errors with the help reverse proxies

    通过反向代理避免CORS错误
  • To respond to point number 10 of the 12 factor app which suggests that the production and dev environments should be as similar as possible.

    为了响应12因子应用程序的第10点,这表明生产和开发环境应尽可能相似。

如何使用docker-compose实现它? (How to implement it using docker-compose ?)

To explain how to implement an HTTPS environment in dev, I will use a small project that will serve as an example throughout this article.

为了说明如何在开发人员中实现HTTPS环境,我将使用一个小项目作为本文的示例。

This project is based on 2 microservices:

该项目基于2种微服务:

  • An “API” written in Flask / Python

    用Flask / Python编写的“ API”
  • A whoami container (it’s an image based on Go who return info about the host when you request it)

    一个whoami容器(这是一个基于Go的图像,当您请求时它将返回有关主机的信息)

The HTTP server I will use for this project is Traefik as described in docs:

我将用于此项目的HTTP服务器是Traefik ,如文档所述:

Traefik is an open-source Edge Router that makes publishing your services a fun and easy experience. It receives requests on behalf of your system and finds out which components are responsible for handling them.

Traefik是开源的 边缘路由器 ,使发布服务变得有趣而轻松。 它代表您的系统接收请求,并找出负责处理这些请求的组件。

It’s easy to use and work well with docker-compose.

它易于使用,并且可以与docker-compose配合使用。

Finally, the last utility we will use, and it’s the one who will allow us to use HTTPS locally is mkcert. It allows us to create TLS certificates who are locally trusted by a Certificate Authority installed and managed by mkcert itself.

最后,我们将使用的最后一个实用程序是mkcert ,它是允许我们在本地使用HTTPS的实用程序 。 它允许我们创建由mkcert本身安装和管理的证书颁发机构在本地信任的TLS证书。

这是我们的项目树的样子: (This is what our project tree looks like:)

.
|____docker-compose.yml
|____traefik.config.toml
|____traefik.toml
|____certs
| |____foo.bar.pem
| |____foo.bar-key.pem
|____api
| |____requirements.txt
| |____Dockerfile
| |____main.py

Nothing much to add about it, the main configs file are at the root of the project and the Flask API file got their own folder.

没什么要补充的,主要的配置文件在项目的根目录下,Flask API文件拥有自己的文件夹。

To describe how this works we will review each service from the docker-compose.yml:

为了描述它是如何工作的,我们将检查docker-compose.yml中的每个服务:

version: '3'services:
back-end:
build:
context: api
dockerfile: Dockerfilewhoami:
image: containous/whoami
ports:
- 5001:80traefik:
image: traefik:latest
restart: always
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- $PWD/certs:/etc/certs
- $PWD/traefik.toml:/etc/traefik/traefik.toml
- $PWD/traefik.config.toml:/etc/traefik/traefik.config.toml

The docker-compose file describe 3 services:

docker-compose文件描述了3种服务:

  • The back-end (Flask application)

    后端(Flask应用程序)
  • whoami (The Go based image to return info about the host)

    whoami(基于Go的图像可返回有关主机的信息)
  • traefik (the http/tcp/udp server)

    traefik(http / tcp / udp服务器)

The first service we will review is our extremely complex Flask API. The latter is single-file and consists of a single endpoint that returns “Hello, world” (told you)

我们将审查的第一项服务是极其复杂的Flask API。 后者是单个文件,由单个端点组成,该端点返回“ Hello,world”(告诉您)

main.py:

main.py:

from flask import Flask
app = Flask(__name__)@app.route('/')
def hello_world():
return 'Hello, World!'if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)

Nothing much to add, we just have an app running on localhost on port 5000

没什么可添加的,我们只有一个在端口5000上的本地主机上运行的应用程序

requirements.txt:

requirements.txt:

click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
Werkzeug==1.0.1

Dockerfile:

Dockerfile:

FROM python:latest
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
ADD . /app
EXPOSE 5000
CMD ["python", "main.py"]

This dockerfile is not suited for production because it uses the development server Flask is offering us. For a production grade image, you might want to use an image based on a wsgi server like gunicorn. However, this image is still useful during development, because it allows us to have hot reload of any changes made in our code.

该dockerfile不适合生产,因为它使用Flask为我们提供的开发服务器。 对于生产级图像,您可能要使用基于wsgi服务器(例如gunicorn)的图像。 但是,此映像在开发过程中仍然有用,因为它允许我们热加载代码中所做的任何更改。

The second service we’ll use is a Whoami docker image, there’s no code to write here, we’ll just have to run a container based on this image.

我们将使用的第二项服务是Whoami泊坞窗映像,此处无需编写代码,我们只需要基于该映像运行容器。

The third service that is used in our docker-composer is Traefik. The latter will require two configuration files, a “static” config file which will be the startup file of the application and a “dynamic” config file which will define our routes policies.

我们的docker-composer中使用的第三项服务是Traefik。 后者将需要两个配置文件,一个“静态”配置文件将作为应用程序的启动文件,一个“动态”配置文件将定义我们的路由策略。

traefik.toml (static):

traefik.toml(静态):

[global]
sendAnonymousUsage = false[log]
level = "INFO" # Change to "DEBUG" if you need more informations
format = "common"[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"[providers]
[providers.file]
filename = "/etc/traefik/traefik.config.toml"
watch = true
[api]
insecure = true
dashboard = true

traefik.config.toml (dynamic):

traefik.config.toml(动态):

[http]
[http.routers]# Here we declare the HTTP/HTTPS route to our Flask API, HTTP
# requests will be redirected to HTTPS by using the redirect
# middleware[http.routers.http-to-back-end]
rule = "Host(`foo.bar`)"
service = "back-end"
entrypoints = ["http"]
middlewares = ["redirect"][http.routers.https-to-back-end]
rule = "Host(`foo.bar`)"
service = "back-end"
entrypoints = ["https"]
[http.routers.https-to-back-end.tls]# Here we define another rule for the whoami container
# it needs the /whoami path
# Like the back-end route, it redirect http to https[http.routers.http-to-whoami]
rule = "Host(`foo.bar`) && Path(`/whoami`)"
service = "whoami"
entrypoints = ["http"]
middlewares = ["redirect"][http.routers.https-to-whoami]
rule = "Host(`foo.bar`) && Path(`/whoami`)"
service = "whoami"
entrypoints = ["https"]
[http.routers.https-to-whoami.tls]# We define our services here, both of our service are loadBalancer
# who will redirect to our docker container (back-end or whoami
# based on router rules)[http.services]
[http.services.back-end]
[http.services.back-end.loadBalancer]
passHostHeader = true[[http.services.back-end.loadBalancer.servers]]
url = "http://back-end:5000/"[http.services.whoami]
[http.services.whoami.loadBalancer]
passHostHeader = true[[http.services.whoami.loadBalancer.servers]]
url = "http://whoami:80/"[http.middlewares]
[http.middlewares.redirect.redirectScheme]
scheme = "https"# The path in the container to the tls certificates generated by
# mkcert[tls]
[[tls.certificates]]
certFile = "/etc/certs/foo.bar.pem"
keyFile = "/etc/certs/foo.bar-key.pem"%

Now that we got everything defined, we need one last element to make the stack work with HTTPS locally.

现在我们已经定义了所有内容,我们需要最后一个元素来使堆栈在本地与HTTPS一起使用。

In the Traefik configuration, we defined some TLS certificates to use, to generate those we will simply just use mkcert.

在Traefik配置中,我们定义了一些TLS证书以使用,只需生成mkcert即可生成这些证书。

It’s quite easy to install mkcert on your system:

在系统上安装mkcert很容易:

  • On macOS:

    在macOS上:
brew install mkcert
brew install nss # if you use Firefox
  • For Linux & Windows installation, there are some lines in the documentation who cover your OS:

    对于Linux和Windows安装,文档中的某些行涵盖了您的操作系统:

Once mkcert is installed on your computer, there are 3 steps’ to follow:

一旦在计算机上安装了mkcert,就可以执行以下三个步骤:

Install the local CA:

安装本地CA:

mkcert -install # Install the local CA in the system trust store

Generate your certificates:

生成您的证书:

mkcert foo.bar # Generate foo.bar.pem and foo.bar-key.pen

Modify your /etc/hosts by adding this line at the end of the file:

通过在文件末尾添加以下行来修改/ etc / hosts:

127.0.0.1 foo.bar

Once all those steps are done, you can run your docker-compose stack:

完成所有这些步骤后,即可运行docker-compose堆栈:

docker-compose up
A terminal with stdout from docker-compose showing the 3 services running.
Hurrah !
万岁!

Now you should be able to access the Flask API from your web browser using https://foo.bar:

现在,您应该可以使用https://foo.bar从Web浏览器访问Flask API

A picture showing a web browser with foo.bar address, also show a secured connexion label.
The certificat should be emited by mkcert if you click on it.
如果单击该证书,则应由mkcert发出。

Now if you access https://foo.bar/whoami you should get some info about your whoami container like this:

现在,如果您访问https://foo.bar/whoami,您应该像这样获得有关whoami容器的一些信息:

Hostname: 821c712dd6ce
IP: 127.0.0.1
IP: 172.23.0.3
RemoteAddr: 172.23.0.2:51872
GET /whoami HTTP/1.1
Host: foo.bar
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6)

And if you access whoami directly with localhost:5001:

如果您直接使用localhost:5001访问whoami:

Hostname: 821c712dd6ce
IP: 127.0.0.1
IP: 172.23.0.3
RemoteAddr: 172.23.0.1:43186
GET / HTTP/1.1
Host: localhost:5001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6)

Hostnames are the same, it’s the container id you can get by typing:

主机名是相同的,它是您可以通过输入以下内容获得的容器ID:

docker ps

However, the hosts are different and correspond to either your local TLS certificates domain name or simply your localhost.

但是,主机是不同的,它们对应于您的本地TLS证书域名或仅对应于您的本地主机。

结论: (To conclude:)

This method give you the ability to work in an environment who is closer to your production environment will giving you a way to work on your code without building/deploying to a staging/production area every time to verify some implementation where you might need HTTPS.

这种方法使您能够在离您的生产环境更近的环境中工作,这将为您提供一种处理代码的方法,而无需每次都构建/部署到临时/生产区域来验证可能需要HTTPS的某些实现。

翻译自: https://medium.com/@axel.vl/local-https-development-with-docker-compose-6996328d0166

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值