برنامه‌نویسی

آموزش استفاده از Docker در توسعه‌ی نرم‌افزار

آموزش استفاده از docker در توسعه‌ی نرم‌افزار

در این مقاله قصد داریم تا استفاده از Docker در توسعه‌ی نرم‌افزار را به شما آموزش دهیم اما بهتر است بدانید چرا باید از Docker برای توسعه‌ی نرم‌افزار استفاده کرد؟

چرا باید از Docker برای توسعه‌ی نرم‌افزار استفاده کرد؟

دلایل بسیار زیادی برای استفاده از Docker وجود دارد اما برخی از آن‌ها عبارتند از:

  • محیط توسعه برای همه‌ی اعضای تیم یکسان است و فرقی نمی‌کند که توسعه‌دهندگان از چه سیستم‌عاملی استفاده می‌کنند.
  • محیط development دقیقا همانند محیط production است. این یعنی بدون دردسر و نگرانی می‌توانید عملیات استقرار نرم‌افزار را انجام دهید و برنامه‌ی شما به‌خوبی اجرا خواهد شد.
  • اگر برنامه‌هایی توسعه‌ می‌دهید که نیاز به کامپایل داشته باشند مطمئنا از سختی‌ها و دردسرهای این کار اطلاع دارید. اما با استفاده از Docker دیگر مهم نیست که از چه سیستم‌عاملی استفاده می‌کنید و می‌توانید کامپایل برنامه‌هایتان را درون Docker انجام دهید.
  • برای توسعه‌ی نرم‌افزار فقط به Docker نیاز دارید. این یعنی نیازی نیست که زبان‌های برنامه‌نویسی مختلف را برای توسعه‌ی هر پروژه بر روی سیستم خود نصب کنید. مثلا اگر قصد اجرای یک اسکریپت توسعه داده شده با زبان Ruby را داشته باشید فقط لازم است تا از یک Ruby Docker Image استفاده کنید.
  • شما می‌توانید به چندین نسخه‌ی مختلف از زبان‌های مورد نیاز خود دسترسی داشته باشید. برای مثال شاید بخواهید برنامه‌ای که با زبان Python توسعه داده‌اید را با Python3 اجرا کنید اما فقط Python2 بر روی سیستم شما نصب است. راه حل بسیار ساده است و می‌توانید به‌راحتی با استفاده از Python3 Image برنامه‌ی خود را اجرا کنید.
  • توسعه‌ی نرم‌افزار در Docker باعث شده تا استقرار برنامه بر روی سرور آسان شود زیرا برنامه‌ی نهایی همان‌طور که در Docker شما اجرا می‌شود، به‌ همان صورت نیز در سرور اجرا خواهد شد و کافیست تا کدهای خود را به یک پکیج تبدیل کرده و آن را در سروری با همان Docker Image مستقر کنید. حتی می‌توانید Docker Image خود را به‌همراه کدهایتان به سرور push کرده و آن Image جدید را اجرا کنید.
  • در توسعه‌ی نرم‌افزار با استفاده از Docker می‌توانید برنامه‌ی خود را بدون نیاز به نصب VM در VirtualBox و SSH، با ویرایشگر مورد علاقه خود توسعه دهید.

نحوه‌ی استفاده از Docker

در استفاده از Docker برای توسعه‌ی پروژه‌های مختلف معمولا تفاوت زیادی وجود ندارد اما برای درک بهتر این موضوع در ادامه‌ی مقاله به توسعه‌ی پروژه‌های مختلفی می‌پردازیم:

Ruby

با یک برنامه ساده شروع می‌کنیم که Hello Ruby! را در Console چاپ می‌کند. البته توجه داشته باشید که برای اجرای این اسکریپت نیازی به نصب زبان Ruby نیست. در قدم اول یک فایل با نام hello.rb در پوشه‌ای با نام app ایجاد کنید و کد زیر را در آن قرار دهید:

puts 'Hello Ruby!'

پس از ذخیره‌ی کدهای بالا، در Terminal سیستم‌عامل خود به پوشه‌ی app بروید و با اجرای دستور زیر اسکریپت Ruby اجرا خواهد شد:

docker run --rm -v "$(pwd)":/app -w /app ruby ruby hello.rb

اگر از command line سیستم‌عامل Windows استفاده می‌کنید بایستی $(pwd) را با %CD% جایگزین کنید:

docker run --rm -v "%CD%":/app -w /app ruby ruby hello.rb

به همین سادگی بدون نصب داشتن زبان Ruby بر روی سیستم خود می‌توانید با استفاده از Docker یک اسکریپت توسعه داده شده با زبان Ruby را اجرا کنید. حال بیایید تا یک وابستگی به اسکریپت اضافه کنیم. یک Gemfile در مسیر پروژه ایجاد کنید و کدهای زیر را در آن قرار دهید:

source 'https://rubygems.org'
gem 'hello-world'

در مرحله‌ی بعد فایل hello.rb را با ویرایشگر مورد نظر خود باز کرده و hello-world را در آن require کنید:

require 'hello-world'

puts 'Hello Ruby!'

اگر با زبان Ruby کار کرده باشید می‌دانید که برای نصب وابستگی جدید بایستی دستور bundle install را اجرا کنید تا اسکریپت hello.rb به‌ درستی اجرا شود اما اگر شما این اسکریپت را در یک Docker container اجرا کنید، با خطا روبرو خواهید شد زیرا وابستگی مورد نیاز اسکریپت، در container نصب نشده و برای نصب وابستگی‌های پروژه بهتر است از یک vendor استفاده کنید:

docker run --rm -v "$(pwd)":/app -w /app ruby bundle install --standalone

با اجرای دستور فوق، نصب وابستگی‌های اسکریپت انجام شده و در صورت نیاز کامپایل‌ کدها انجام خواهد شد. اکنون برای استفاده از bundle جدید بایستی require_relative را در ابتدای فایل hello.rb قرار دهیم:

require_relative 'vendor/bundle/bundler/setup'
require 'hello-world'

puts 'Hello Ruby!'

پس از ذخیره‌ی فایل، با اجرای دستور زیر می‌توانید خروجی اسکریپت را در Console خود مشاهده کنید:

docker run --rm -v "$(pwd)":/app -w /app ruby ruby hello.rb

حتی اگر بخواهید این اسکریپت را با ورژن خاصی از Ruby اجرا کنید می‌توانید به‌صورت زیر عمل کنید:

docker run --rm -v "$(pwd)":/app -w /app ruby:2.4 ruby hello.rb

راه‌اندازی برنامه‌ی وب با Ruby

برای ساخت برنامه‌های وب نیاز است تا یک پورت را باز کنیم و این کار در Docker با اضافه کردن -p PORT:PORT به دستور docker run انجام می‌شود. کدهای زیر را در یک فایل با نام webapp.rb ذخیره کنید:

require_relative 'bundle/bundler/setup'
require 'sinatra'

set :port, 8080
set :bind, '0.0.0.0' # required to bind to all interfaces

get '/' do
  "Hello World!"
end

در مرحله‌ی بعد sinatra را به Gemfile اضافه کرده و با دستور bundle install این gem جدید را در Docker container نصب کنید. همچنین sinatra به یک پیش‌نیاز به‌نام thin نیاز دارد بنابراین بایستی با اجرای دستور زیر آن را نصب کرده:

docker run --rm -it -v "$(pwd)":/docktest -w /docktest ruby gem install thin

و در نهایت با اجرای دستور زیر برنامه‌ی وب ما اجرا خواهد شد:

docker run -i -t --rm -v "$(pwd)":/app -w /app -p 8080:8080 ruby ruby webapp.rb

برای مشاهده‌ی برنامه می‌توانید وارد لینک localhost:8080 شوید.

Node.js

برای ایجاد اسکریپت Node.js و اجرای آن با Docker بایستی در وهله‌ی اول پیش‌نیازهای مورد نیاز را در Docker container نصب کنید:

docker run --rm -it -v $PWD:/app -w /app node npm install hello-world-npm

سپس کدهای زیر را در در فایلی با نام hello.js در پوشه‌ی app ذخیره کرده:

const helloWorld = require('hello-world-npm');
console.log(helloWorld());
console.log("Hello Node!");

در نهایت برای اجرای اسکریپت می‌توانید از دستور زیر استفاده کنید:

docker run --rm -it -v $PWD:/app -w /app node hello.js

Go

کدهای زیر را در یک با نام hello.go ذخیره کنید:

package main

import (
	"fmt"
	hello "github.com/treeder/go-hello-world"
)

func main() {
	fmt.Println(hello.Hello())
	fmt.Println("Hello Go!")
}

سپس دستورهای زیر را به‌ترتیب برای نصب وابستگی‌ها و کامپایل برنامه اجرا کنید:

docker run --rm -i -v $PWD:/app -w /app golang go get github.com/treeder/go-hello-world
docker run --rm -i -v $PWD:/app -w /app golang go build -o myapp
docker run --rm -i -v $PWD:/app -w /app golang ./myapp

جمع‌بندی

ما در تمام مثال‌های قبل از --rm استفاده کردیم و این سوئیچ باعث می‌شود تا container ایجاد شده پس از اجرای دستور مورد نظر ما حذف شود. حال شاید در برنامه‌‌ی شما یک وابستگی مانند RocksDB وجود داشته باشد که زمان زیادی برای build آن نیاز است. در چنین سناریویی می‌توانید از ترفند زیر استفاده کنید:

docker run --name goapp -it -v $PWD:/app -w /app golang sh -c "go build -o myapp && ./myapp" || docker start -ia goapp

با اجرای دستور فوق یک container با نام goapp ساخته شده و دستور go build -o myapp && ./myapp را اجرا می‌کند اما حذف نخواهد شد بنابراین می‌توانید هر زمان که دوست داشته باشید با اجرای دستور docker start -ia goapp بدون نیاز به کامپایل مجدد برنامه، آن container را اجرا کنید.

مطمئنا تابه‌حال متوجه شده‌اید که توسعه به کمک Docker تغییری در روند توسعه‌ی شما ایجاد نمی‌کند اما می‌توانید به مزایایی که در ابتدای مقاله به آن‌ها اشاره کرده بودیم دست پیدا کنید.

منبع: https://medium.com/better-programming/why-and-how-to-use-docker-for-development-a156c1de3b24