2016-10-04 24 views

Trả lời

4

Có nhiều cách để đạt được điều này tùy thuộc vào thiết lập của bạn. Một cách phổ biến là thiết lập nginx ở phía trước vùng chứa Docker của bạn và xử lý hoàn toàn các chứng chỉ trong cấu hình nginx của bạn.

Cấu hình nginx có thể chứa danh sách 'usptreams' (vùng chứa Docker) và 'máy chủ' của bạn về cơ bản ánh xạ các yêu cầu đến các luồng ngược cụ thể. Là một phần của ánh xạ đó, bạn cũng có thể xử lý SSL.

Bạn có thể sử dụng certbot để giúp bạn thiết lập điều này.

+0

Tôi đang tìm thêm hướng dẫn từng bước để thực hiện những gì tôi mô tả. – jsejcksn

+0

Bạn không thể đạt được điều này - có quá nhiều biến thể và câu trả lời Stack Overflow không nhằm mục đích "hướng dẫn từng bước". Bạn có thể nhận được phản hồi tốt hơn nếu bạn mô tả những gì bạn đã thử và đặt một câu hỏi cụ thể, – duncanhall

2

Bạn có thể có một cái nhìn ở đây: https://certbot.eff.org/docs/using.html?highlight=docker#running-with-docker

Sau đó, những gì cá nhân tôi làm là:

  1. Tạo một khối lượng Docker để lưu trữ các Certs và tạo ra các Certs với hình ảnh trên
  2. Tạo Mạng do người dùng định nghĩa Docker (https://docs.docker.com/engine/userguide/networking/#/user-defined-networks)
  3. Tạo hình ảnh dựa trên nginx với cấu hình của bạn (có thể this sẽ hữu ích)
  4. Tạo vùng chứa Nginx dựa trên hình ảnh của bạn, gắn ổ đĩa vào nó và kết nối với mạng (cũng chuyển tiếp cổng 80 và 443 đến bất kỳ thứ gì bạn muốn)
  5. Tôi sẽ tạo vùng chứa cho ứng dụng node.js của bạn và kết nối nó vào cùng một mạng

Bây giờ nếu bạn đã định cấu hình nginx đúng (trỏ tới đúng đường dẫn TLS và proxy tới URL thích hợp, như http://my-app:3210), bạn sẽ có quyền truy cập vào ứng dụng của mình bằng https.

16

Điều đầu tiên tôi đã làm là tạo một hình ảnh docker dựa trên express đơn giản.

Tôi đang sử dụng app.js sau, lấy từ nhanh của hello world example trong tài liệu của họ:

var express = require('express'); 
var app = express(); 

app.get('/', function (req, res) { 
    res.send('Hello World!'); 
}); 

app.listen(3000, function() { 
    console.log('Example app listening on port 3000!'); 
}); 

Tôi cũng đã kết thúc với packages.json tập tin sau đây sau khi chạy npm init của họ trong cùng một doc:

{ 
    "name": "exampleexpress", 
    "version": "1.0.0", 
    "description": "", 
    "main": "app.js", 
    "scripts": { 
    "test": "echo \"Error: no test specified\" && exit 1" 
    }, 
    "author": "", 
    "license": "ISC", 
    "dependencies": { 
    "express": "^4.14.0" 
    } 
} 

Tôi đã tạo Dockerfile sau:

FROM node:onbuild 
EXPOSE 3000 
CMD node app.js 

Đây là đầu ra khi tôi thực hiện bước docker build của mình.Tôi đã gỡ bỏ hầu hết các npm install đầu ra cho ngắn gọn vì lợi ích:

$ docker build -t exampleexpress . 
Sending build context to Docker daemon 1.262 MB 
Step 1 : FROM node:onbuild 
# Executing 3 build triggers... 
Step 1 : COPY package.json /usr/src/app/ 
Step 1 : RUN npm install 
---> Running in 981ca7cb7256 
npm info it worked if it ends with ok 
<snip> 
npm info ok 
Step 1 : COPY . /usr/src/app 
---> cf82ea76e369 
Removing intermediate container ccd3f79f8de3 
Removing intermediate container 391d27f33348 
Removing intermediate container 1c4feaccd08e 
Step 2 : EXPOSE 3000 
---> Running in 408ac1c8bbd8 
---> c65c7e1bdb94 
Removing intermediate container 408ac1c8bbd8 
Step 3 : CMD node app.js 
---> Running in f882a3a126b0 
---> 5f0f03885df0 
Removing intermediate container f882a3a126b0 
Successfully built 5f0f03885df0 

Chạy hình ảnh này làm việc như thế này:

$ docker run -d --name helloworld -p 3000:3000 exampleexpress 
$ curl 127.0.0.1:3000 
Hello World! 

Chúng tôi có thể làm sạch này lên bằng cách thực hiện: docker rm -f helloworld


Bây giờ, tôi đã có trang web dựa trên cơ bản của tôi chạy trong một thùng chứa Docker, nhưng nó chưa có bất kỳ thiết lập TLS nào. Nhìn lại tài liệu expressjs, security best practice khi sử dụng TLS là sử dụng nginx.

Vì tôi muốn giới thiệu một thành phần mới (nginx), tôi sẽ làm điều đó với một container thứ hai.

Vì nginx sẽ cần một số chứng chỉ để làm việc, hãy tiếp tục và tạo các chứng chỉ với ứng dụng khách cho phép. Tài liệu allowencrypt về cách sử dụng allowencrypt trong Docker có thể được tìm thấy tại đây: http://letsencrypt.readthedocs.io/en/latest/using.html#running-with-docker

Chạy các lệnh sau để tạo chứng chỉ ban đầu. Bạn sẽ cần phải chạy nó trên một hệ thống được kết nối với internet công cộng, và có cổng 80/443 có thể truy cập từ các máy chủ cho phép. Bạn cũng sẽ cần phải có tên DNS của bạn thiết lập và trỏ đến hộp mà bạn chạy này trên:

export LETSENCRYPT_EMAIL=<youremailaddress> 
export DNSNAME=www.example.com 

docker run --rm \ 
    -p 443:443 -p 80:80 --name letsencrypt \ 
    -v "/etc/letsencrypt:/etc/letsencrypt" \ 
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ 
    quay.io/letsencrypt/letsencrypt:latest \ 
    certonly -n -m $LETSENCRYPT_EMAIL -d $DNSNAME --standalone --agree-tos 

Hãy chắc chắn rằng để thay thế các giá trị cho LETSENCRYPT_EMAILDNSNAME. Địa chỉ email được sử dụng cho thông báo hết hạn.


Bây giờ, hãy thiết lập máy chủ nginx sẽ sử dụng chứng chỉ mới được tạo này. Thứ nhất, chúng tôi sẽ cần một tập tin cấu hình nginx được cấu hình cho TLS:

user nginx; 
worker_processes 1; 

error_log /var/log/nginx/error.log warn; 
pid  /var/run/nginx.pid; 


events { 
    worker_connections 1024; 
} 


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

    log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 
         '$status $body_bytes_sent "$http_referer" ' 
         '"$http_user_agent" "$http_x_forwarded_for"'; 

    access_log /dev/stdout main; 
    sendfile  on; 
    keepalive_timeout 65; 

    server { 
     listen  80; 
     server_name _; 
     return 301 https://$host$request_uri; 
    } 

    server { 
     listen    443 ssl; 
     #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; 
     server_name   www.example.com; 
     ssl_certificate  /etc/letsencrypt/live/www.example.com/fullchain.pem; 
     ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; 
     ssl_protocols  TLSv1 TLSv1.1 TLSv1.2; 
     ssl_ciphers   HIGH:!aNULL:!MD5; 

     location ^~ /.well-known/ { 
      root /usr/share/nginx/html; 
      allow all; 
     } 

     location/{ 
      proxy_set_header Host $host; 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_pass http://expresshelloworld:3000; 
     } 
    } 
} 

Chúng ta có thể đặt tập tin cấu hình này thành hình ảnh tùy chỉnh nginx riêng của chúng tôi với Dockerfile sau:

FROM nginx:alpine 
COPY nginx.conf /etc/nginx/nginx.conf 

Điều này có thể xây dựng với lệnh sau: docker build -t expressnginx .

Tiếp theo, chúng ta sẽ tạo một mạng tùy chỉnh để chúng ta có thể tận dụng tính năng phát hiện dịch vụ Docker của:

docker network create -d bridge expressnet 

Bây giờ, chúng ta có thể cháy lên các container helloworld và nginx:

docker run -d \ 
    --name expresshelloworld --net expressnet exampleexpress 
docker run -d -p 80:80 -p 443:443 \ 
    --name expressnginx --net expressnet \ 
    -v /etc/letsencrypt:/etc/letsencrypt \ 
    -v /usr/share/nginx/html:/usr/share/nginx/html \ 
    expressnginx 

Kiểm tra nginx rằng đã đưa ra đúng bằng cách nhìn vào đầu ra của docker logs expressnginx.

Tệp cấu hình nginx sẽ chuyển hướng mọi yêu cầu trên cổng 80 qua cổng 443.Chúng ta có thể kiểm tra rằng bằng cách chạy như sau:

curl -v http://www.example.com/ 

Chúng tôi cũng nên, vào thời điểm này, có thể đưa ra một kết nối TLS thành công, và xem phản ứng của Hello World! của chúng tôi trở lại:

curl -v https://www.example.com/ 

Bây giờ, để thiết lập quy trình gia hạn. Nginx.conf ở trên có các điều khoản cho đường dẫn cho phép. Được biết đến cho phương thức xác minh webroot. Nếu bạn chạy lệnh sau, lệnh này sẽ xử lý gia hạn. Thông thường, bạn sẽ chạy lệnh này trên một số loại cron để certs của bạn sẽ được gia hạn trước khi hết hạn:

export [email protected] 
export DNSNAME=www.example.com 

docker run --rm --name letsencrypt \ 
    -v "/etc/letsencrypt:/etc/letsencrypt" \ 
    -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ 
    -v "/usr/share/nginx/html:/usr/share/nginx/html" \ 
    quay.io/letsencrypt/letsencrypt:latest \ 
    certonly -n --webroot -w /usr/share/nginx/html -d $DNSNAME --agree-tos 
+0

Hướng dẫn tuyệt vời, đây là câu trả lời được chấp nhận –

0

cuối Mặt trận - Nginx - mà nghe 443 cảng, và proxy để beck kết thúc

Back end - bạn docker container

Các vấn đề liên quan