Docker، به عنوان یک روش کارآمد برای اجرای برنامه‌های تحت وب قابل استفاده است. در صورتی که بخواهید چندین برنامه را در یک میزبان Docker اجرا کنید، شما باید یک پروکسی معکوس (Reverse Proxy) برای آن تنظیم نمایید؛ زیرا تنها باید پورت‌های 80 و 443 را در معرض دید سایر نقاط جهان قرار دهید.

Traefik یک Reverse Proxy برای Docker است که شامل داشبورد نظارت است. در این آموزش، از Traefik به منظور مسیریابی درخواست‌ها به دو container مختلف برنامه وب استفاده شده است. این دو container شامل؛ یک container وردپرس و یک container مربوط به Adminer است که هردو از پایگاه داده MySQL استفاده می‌کنند. با استفاده از Let's Encrypt می‌توانید Traefik را به گونه‌ای پیکربندی نمایید که همه درخواست‌ها را در HTTPS ارائه دهد.

 

به منظور پیگیری این آموزش، به موارد زیر نیاز دارید:

یک سرور اوبونتو 18.04 که شامل یک کاربر sudo غیر root و یک فایروال است.

Docker نصب شده بر روی سرور اوبونتو.

Docker Compose نصب شده در اوبونتو.

یک دامنه و سه رکورد A، بصورت db-admin ،blog و monitor که هر کدام به آدرس IP سرور شما نگاشت شده‌اند.

دقت کنید که در طول این آموزش، در فایل‌ها و مثال‌های پیکربندی باید دامنه خود را با your_domain جایگزین نمایید.

 

این مطلب نیز ممکن است برای شما مفید باشد: نحوه نمایش containerها درDocker

 

مرحله 1 - پیکربندی و اجرای Traefik

پروژه Traefik دارای یک image رسمی Docker است؛ بنابراین در اینجا، از آن برای اجرای Traefik در یک Docker Container استفاده شده است.

اما قبل از اینکه Traefik container خود را راه‌اندازی کنید، باید یک فایل پیکربندی ایجاد کرده و یک رمز عبور تنظیم نمایید تا بتوانید به داشبورد نظارت دسترسی داشته باشید.

در اینجا از برنامه htpasswd برای ایجاد این رمز عبور استفاده شده است. با استفاده از دستور زیر می‌توانید این ابزار را که در بسته apache2-utils موجود است، نصب کنید:

sudo apt-get install apache2-utils

سپس رمز عبور را به صورت زیر با دستور htpasswd ایجاد نمایید. secure_password را با گذرواژه مورد نظر برای کاربر ادمین Traefik جایگزین کنید:

htpasswd -nb admin secure_password

خروجی برنامه به صورت زیر خواهد بود:

Output
admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/

از این خروجی در فایل پیکربندی Traefik به منظور راه‌اندازی احراز هویت HTTP Basic برای داشبورد بررسی و نظارت بر سلامت Traefik استفاده خواهید کرد. بنابراین خروجی را به طور کامل کپی کنید تا بعداً آن را جایگذاری نمایید.

 

به منظور پیکربندی سرور Traefik، یک فایل پیکربندی جدید به نام traefik.toml با استفاده از قالب TOML ایجاد کنید. TOML، یک زبان پیکربندی شبیه به فایل‌های INI است؛ اما استاندارد شده است. این فایل به شما امکان می‌دهد سرور Traefik و ارائه دهندگان آن را پیکربندی نمایید. در این آموزش، از سه ارائه دهنده موجود Traefik استفاده شده است: api ،docker و acme که برای پشتیبانی از TLS با استفاده از Let's Encrypt استفاده می‌شود.

فایل جدید خود را بصورت زیر باز کنید:

nano traefik.toml

ابتدا دو entrypoint با نام‌های http و https اضافه نمایید. بطوری که همه پس زمینه‌ها به طور پیش فرض به آن‌ها دسترسی خواهند داشت:

                            traefik.toml

defaultEntryPoints = ["http", "https"]

سپس در این فایل، نقاط ورود http و https را پیکربندی کنید.

 

در مرحله بعد، ارائه دهنده api را پیکربندی نمایید که به شما امکان دسترسی به رابط داشبورد را می‌دهد. در اینجا باید خروجی دستور htpasswd را قرار دهید:

                               traefik.toml

...
[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]

[api]
entrypoint="dashboard"

داشبورد، یک برنامه وب جداگانه است که در Traefik container اجرا می‌شود. در اینجا داشبورد بگونه‌ای تنظیم شده است که روی پورت 8080 اجرا شود.

بخش entrypoints.dashboard، نحوه ارتباط شما با ارائه دهنده api را تنظیم می‌کند و بخش entrypoints.dashboard.auth.basic احراز هویت HTTP Basic را برای داشبورد پیکربندی می‌نماید. از خروجی دستور htpasswd که اجرا کرده‌اید، برای مقدار ورودی users استفاده کنید. شما می‌توانید ورودهای اضافی را با جدا کردن آن‌ها با کاما مشخص نمایید.

 

این مطلب نیز ممکن است برای شما مفید باشد: نحوه اتصال به Docker Container

 

ما اولین entryPoint خود را تعریف کرده‌ایم؛ اما برای ارتباطات استاندارد HTTP و HTTPS که به سمت ارائه دهنده api هدایت نمی‌شود، باید دیگر موارد را نیز تعریف کنیم. بخش entryPoints، آدرس‌هایی را پیکربندی می‌کند که Traefik و container‌های پروکسی می‌توانند برروی آن‌ها کار کنند. بدین منظور خطوط زیر را به فایل (در بخش entryPoints) اضافه نمایید:

                             traefik.toml

...
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]
...

بخش http، پورت 80 را کنترل می‌کند؛ در حالی که بخش https از پورت 443 برای TLS/SSL استفاده می‌نماید. در اینجا به طور خودکار تمام ترافیک‌های پورت 80 به نقطه ورود https هدایت شده است تا اتصالات ایمن برای همه درخواست‌ها اعمال شود.

 

در مرحله بعد، این بخش را برای تنظیم پشتیبانی از Certificate Let's Encrypt برای Traefik اضافه نمایید:

                             traefik.toml

...
[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

این بخش acme نامیده می‌شود؛ زیرا ACME نام پروتکلی است که برای ارتباط با Let's Encrypt به منظور مدیریت گواهی‌ها استفاده می‌شود. سرویس Let's Encrypt نیاز به ثبت نام با یک آدرس ایمیل معتبر دارد؛ بنابراین به منظور اینکه Traefik برای میزبانان ما گواهینامه ایجاد کند، باید بخش email را برروی آدرس ایمیل خود تنظیم نمایید. سپس می‌توانید تعیین کنید که اطلاعات دریافتی از Let's Encrypt را در یک فایل JSON به نام acme.json ذخیره نماید. بخش enterPoint باید به پورت 443 کنترل entry point اشاره کند که در اینجا نقطه ورود https است.

بخش onHostRule تعیین می‌کند که Traefik چگونه باید در مورد تولید گواهینامه عمل کند. در اینجا می‌خواهیم به محض ایجاد containerهای خود با نام‌های میزبان مشخص، گواهینامه‌های خود را دریافت کنیم. این کاری است که تنظیمات onHostRule انجام می‌دهد.

بخش acme.httpChallenge به ما اجازه می‌دهد تا مشخص کنیم که چگونه Let’s Encrypt می‌تواند تأیید کند که باید گواهی تولید شود. در اینجا، آن را به گونه‌ای پیکربندی می‌کنیم که به عنوان بخشی از چالش از طریق http entrypiont به فایل ارائه شود.

 

در نهایت، با افزودن خطوط زیر به فایل، ارائه دهنده docker را پیکربندی نمایید:

                           traefik.toml

...
[docker]
domain = "your_domain"
watch = true
network = "web"

ارائه دهنده docker، ابزار Traefik را قادر می‌سازد تا به عنوان یک پروکسی در مقابل Docker container عمل کند. در اینجا، ارائه دهنده را بگونه‌ای پیکربندی کرده‌ایم که containerهای جدیدی را در شبکه وب (که به زودی ایجاد خواهیم کرد) جستجو نماید و آن‌ها را به عنوان زیر دامنه‌های your_domain نشان دهد.

 

این مطلب نیز ممکن است برای شما مفید باشد: حذف imageها، containerها و Volumeهای Docker

 

در این مرحله، traefik.toml باید دارای محتویات زیر باشد:

                                   traefik.toml

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]

[api]
entrypoint="dashboard"

[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

[docker]
domain = "your_domain"
watch = true
network = "web"

پس از آن، فایل را ذخیره کرده و از ویرایشگر خارج شوید. پس از این تنظیمات، اکنون شما می‌توانید Traefik را اجرا نمایید.

 

مرحله 2 – اجرای Traefik Container

در مرحله بعد، یک شبکه Docker به منظور به اشتراک گذاری با container برای پروکسی ایجاد کنید. شبکه Docker برای برنامه‌هایی که با استفاده از Docker Compose اجرا می‌شوند، ضروری است. در اینجا، این شبکه را web نامیده‌ایم.

docker network create web

وقتی Traefik container شروع به کار می‌کند، ما آن را به این شبکه اضافه می‌کنیم. بدین صورت، بعداً می‌توانیم containerهای بیشتری را به این شبکه اضافه نماییم تا Traefik به پروکسی آن‌ها دسترسی پیدا کند.

در مرحله بعد، یک فایل خالی ایجاد نمایید که حاوی اطلاعات Let's Encrypt شما باشد. ما این را در container به اشتراک می‌گذاریم تا Traefik بتواند از آن استفاده کند:

touch acme.json

Traefik، تنها در صورتی می‌تواند از این فایل استفاده کند که کاربر اصلی داخل container دارای دسترسی خواندن و نوشتن در آن باشد. بدین منظور باید مجوزهای acme.json را قفل کنید تا تنها صاحب فایل اجازه خواندن و نوشتن را داشته باشد.

chmod 600 acme.json

هنگامی‌که فایل به Docker منتقل می‌شود، به طور خودکار مالک آن به کاربر اصلی داخل container تغییر می‌یابد.

 

در نهایت، Traefik container را با دستور زیر ایجاد نمایید:

    docker run -d \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v $PWD/traefik.toml:/traefik.toml \
      -v $PWD/acme.json:/acme.json \
      -p 80:80 \
      -p 443:443 \
      -l traefik.frontend.rule=Host:monitor.your_domain \
      -l traefik.port=8080 \
      --network web \
      --name traefik \
      traefik:1.7-alpine

شرح این دستور در ادامه بیان شده است.

از پرچم d- به منظور اجرای container در پس زمینه به عنوان یک daemon استفاده کرده‌ایم. سپس فایل docker.sock خود را در container به اشتراک گذاشته‌ایم تا فرآیند Traefik بتواند تغییرات container را شنود کند. علاوه بر این، فایل پیکربندی traefik.toml و فایل acme.json  ایجاد شده در container را به اشتراک گذاشته‌ایم.

در مرحله بعد، پورت‌های 80 و 443 میزبان Docker خود را به پورت‌های مشابه در Traefik container نگاشت کرده‌ایم تا Traefik تمام ترافیک‌های HTTP و HTTPS  سرور را دریافت کند.

سپس دو برچسب Docker تنظیم کرده‌ایم که به Traefik می‌گوید، ترافیک را به نام میزبان monitor.your_domain به پورت 8080 در Traefik container هدایت کند.

شبکه container را برروی web تنظیم کرده و container را به traefik نام‌گذاری نموده‌ایم.

 

در نهایت، از image مربوط به traefik: 1.7-alpine (به دلیل حجم کم) برای این container استفاده کرده‌ایم.

ENTRYPOINT مربوط به یک Docker image فرمانی است که همیشه هنگام ایجاد یک container از روی image اجرا می‌شود. در این مورد، دستور، بصورت باینری traefik درون container است. هنگام راه‌اندازی container، شما می‌توانید آرگومان‌های بیشتری به آن دستور ارسال نمایید. با این حال ما همه تنظیمات خود را در فایل traefik.toml پیکربندی کرده‌ایم.

با راه‌اندازی container، اکنون داشبوردی دارید که می‌توانید به آن دسترسی داشته باشید تا از سلامت containerهای خود مطلع شوید. همچنین می‌توانید از این داشبورد برای شبیه سازی frontendها و backenهایی که Traefik ثبت کرده است، استفاده کنید.

با وارد کردن https: //monitor.your_domain در مرورگر می‌توانید به داشبورد نظارت دسترسی پیدا نمایید. پس از دسترسی، از شما خواسته می‌شود نام کاربری و رمز عبور خود را وارد نمایید؛ که این‌ها مواردی هستند که در مرحله 1 پیکربندی کرده‌اید.

پس از ورود به سیستم، رابطی مشابه زیر را مشاهده خواهید کرد:

 

در ابتدا چیزهای زیادی برای دیدن وجود ندارد؛ اما این پنجره را باز بگذارید و با افزودن container برای کار با Traefik تغییر محتویات آن را مشاهده نمایید.

اکنون می‌توانید پروکسی Traefik خود را به منظور کار با Docker پیکربندی شده و نظارت بر دیگر Docker Container اجرا کنید.

 

این مطلب نیز ممکن است برای شما مفید باشد: به اشتراک گذاری داده ها بین Docker Container

 

مرحله 3 - ثبت containerها با Traefik

با فعال شدن Traefik container، آماده اجرای برنامه‌های کاربردی در پشت آن خواهید بود. به عنوان مثال، بیایید cotainerهای زیر را در پشت Traefik راه‌اندازی کنیم:

  • یک blog با استفاده از official Wordpress image.
  • یک سرور مدیریت پایگاه داده با استفاده از official Adminer image.

در ادامه، این دو برنامه را با Docker Compose و با استفاده از یک فایل docker-compose.yml مدیریت خواهیم کرد. بدین منظور، ایتدا فایل docker-compose.yml را در ویرایشگر خود باز نمایید:

nano docker-compose.yml

خطوط زیر را به فایل اضافه کنید تا نسخه و شبکه‌های مورد استفاده مشخص شود:

docker-compose.yml

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

در اینجا، از Docker Compose نسخه 3 استفاده می‌کنیم.

 

برای اینکه Traefik برنامه‌های ما را بشناسد، آن‌ها باید بخشی از یک شبکه باشند و از آنجا که ما شبکه را به صورت دستی ایجاد کرده‌ایم، با مشخص کردن نام شبکه web و تنظیم external برروی true، آن را به داخل شبکه وارد می‌کنیم. سپس باید یک شبکه دیگر تعریف نماییم تا بتوانیم containerهای آشکار خود را به یک پایگاه داده متصل کنیم و از طریق Traefik آن‌ها را مخفی نماییم. در اینجا، ما این شبکه را internal نامیده‌ایم.

در مرحله بعد، هر یک از سرویس‌های خود را یکی یکی تعریف می‌کنیم. بیایید با container مربوط به blog شروع کنیم که بر اساس official Wordpress image است. پیکربندی زیر را به فایل اضافه نمایید:

docker-compose.yml

version: "3"
...

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

بخش environment به شما امکان می‌دهد، متغیرهای محیطی را که در داخل container تنظیم می‌شوند، مشخص کنید. با عدم تعیین یک مقدار برای WORDPRESS_DB_PASSWORD، به Docker Compose می‌گویید که مقدار را از shell خود دریافت کرده و هنگام ایجاد container، آن را ارسال نماید. قبل از راه‌اندازی container باید این متغیر محیطی را در shell خود تعریف نمایید. به این ترتیب ما رمزهای عبور را در فایل پیکربندی وارد نمی‌کنیم.

 

این مطلب نیز ممکن است برای شما مفید باشد: اجرای Docker Container در پس زمینه (حالت Detached)

 

بخش lables جایی است که مقادیر پیکربندی Traefik را مشخص می‌کنید. برچسب‌های Docker به تنهایی کاری انجام نمی‌دهند؛ اما Traefik، این مقادیر را می‌خواند تا بداند چگونه با containerها رفتار کند. کارکرد هر یک از این برچسب‌ها به شرح زیر است:

traefik.backend، نام سرویس backend را در Traefik (که به محتویات blog واقعی اشاره می‌کند) مشخص می‌نماید.

traefik.frontend.rule=Host:blog.your_domain، به Traefik می‌گوید که میزبان درخواست شده را بررسی کند. چنانچه با الگوی blog.yow_domain مطابقت داشت، باید ترافیک را به container مربوط به blog هدایت کند.

traefik.docker.network=web مشخص می‌کند که برای Traefik در کدام شبکه به دنبال IP داخلی این container باشید. از آنجا که Traefik container ما به تمام اطلاعات Docker دسترسی دارد، چنانچه این بخش را مشخص نکنیم، به طور بالقوه IP شبکه داخلی را می‌گیرد.

traefik.port، پورت آشکاری را مشخص می‌کند که Traefik باید از آن برای هدایت ترافیک به این container استفاده کند.

با این پیکربندی، تمام ترافیک ارسال شده به پورت 80 میزبان Docker ما به containe مربوط به blog هدایت می‌شود.

ما این container را به دو شبکه مختلف اختصاص می‌دهیم تا Traefik بتواند آن را از طریق شبکه web پیدا کرده و بتواند از طریق شبکه داخلی با container پایگاه داده ارتباط برقرار نماید.

در نهایت، بخش depend_on به Docker Compose می‌گوید که این container باید بعد از اجرای برنامه‌های وابسته خود، شروع به کار کند. از آنجا که وردپرس برای اجرا نیاز به پایگاه داده دارد، قبل از راه‌اندازی container مربوط به blog، باید container مربوط بهmysql  خود را اجرا کنید.

 

در مرحله بعد، با افزودن موارد زیر به فایل خود، سرویس MySQL را پیکربندی نمایید:

                           docker-compose.yml

services:
...
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

در اینجا از image رسمی MySQL 5.7 برای این container استفاده می‌کنیم. همانطور که قابل مشاهده است، ما بار دیگر از یک آیتم environment بدون مقدار استفاده کرده‌ایم. متغیرهای MYSQL_ROOT_PASSWORD و WORDPRESS_DB_PASSWORD باید برروی یک مقدار تنظیم شوند تا مطمئن شوید container وردپرس‌تان می‌تواند با MySQL ارتباط برقرار کند. از آنجایی که نمی‌خواهیم container مربوط به mysql را در معرض نمایش Traefik یا دنیای خارج قرار دهیم؛ بنابراین این container را تنها به شبکه داخلی اختصاص می‌دهیم. از آنجایی که Traefik به سوکت Docker دسترسی دارد، این فرایند همچنان بطور پیش فرض container مربوط به mysql را نشان می‌دهد؛ بنابراین باید برچسب traefik.enable = false را اضافه کنیم تا مشخص شود که Traefik نباید این container را آشکارا نمایش دهد.

 

در نهایت، پیکربندی زیر را برای تعریف container مربوط به Adminer اضافه نمایید:

                             docker-compose.yml

services:
...
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

این container بر اساس official Adminer image است. پیکربندی network و depends_on برای این container دقیقاً با آنچه برای container مربوط به blog استفاده کردیم، مطابقت دارد.

با این حال، از آنجا که ما تمام ترافیک‌های پورت 80 برروی میزبان Docker خود را مستقیماً به container مربوط به blog هدایت می‌کنیم، باید این container را به گونه دیگری پیکربندی نماییم تا ترافیک به container مربوط به adminer برسد. خط traefik.frontend.rule = Host:db-admin.your_domain به Traefik می‌گوید که میزبان درخواست شده را بررسی کند. اگر با الگوی db-admin.y_domain مطابقت داشته باشد، Traefik ترافیک را به container مربوط به adminer هدایت می‌کند.

 

در این مرحله، docker-compose.yml باید دارای محتویات زیر باشد:

                           docker-compose.yml

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

فایل را ذخیره کرده و از ویرایشگر متن خارج شوید.

 

این مطلب نیز ممکن است برای شما مفید باشد: نحوه نامگذاری یا تغییر نام Docker Containers

 

سپس، مقادیری را در shell خود برای متغیرهای WORDPRESS_DB_PASSWORD و MYSQL_ROOT_PASSWORD قبل از راه‌اندازی containerها تنظیم کنید:

export WORDPRESS_DB_PASSWORD=secure_database_password
export MYSQL_ROOT_PASSWORD=secure_database_password

secure_database_password را با گذرواژه پایگاه داده مورد نظر خود جایگزین نمایید. به یاد داشته باشید که از رمز عبور یکسان برای WORDPRESS_DB_PASSWORD و MYSQL_ROOT_PASSWORD استفاده کنید.

با تنظیم این متغیرها، containerها را با استفاده از docker-compose اجرا نمایید:

docker-compose up -d

اکنون اگر نگاه دیگری به داشبورد مدیریت Traefik بیندازید، مشاهده خواهید کرد که برای دو سرور آشکار، یک backend و یک frontend وجود دارد:

 

به وب سایت blog.your_domain بروید و your_domain را با دامنه خود جایگزین نمایید. شما به یک اتصال TLS هدایت خواهید شد و می‌توانید تنظیمات Wordpress را تکمیل کنید:

 

اکنون با مراجعه به آدرس db-admin.your_domain در مرورگر خود، مجدداً می‌توانید به Adminer دسترسی پیدا کنید. در اینجا نیز دامنه خود را با your_domain جایگزین نمایید. Container مربوط به mysql در معرض دنیای خارج نیست؛ اما container مربوط به adminer از طریق شبکه داخلی Docker (که با استفاده از نام mysql container به عنوان نام میزبان به اشتراک می‌گذارد)، به آن دسترسی دارد.

در صفحه ورود به سیستم Adminer، از root به عنوان نام کاربری، از mysql به عنوان سرور و از مقدار تعیین شده برای MYSQL_ROOT_PASSWORD برای رمز عبور استفاده کنید. پس از ورود به سیستم، رابط کاربری Adminer را مشاهده خواهید کرد:

 

هر دو سایت اکنون کار می‌کنند و شما می‌توانید از داشبورد monitor.your_domain برای نظارت بر برنامه‌های خود استفاده نمایید.

 

 

 

منبع:

digitalocean