안녕하세요!
AWS같은 public 클라우드를 작업하다보면 늘 새로운 VPC를 만들어야하고 Subnet을 설정하고, 라우팅테이블로 연결해주고 등등 여러가지 설정작업들이 많은데요, 늘 반복되는 작접을 좀 편하고 빠르고 간단하게 할 수 없을까 생각을 종종 해왔습니다. 
 
바로 이것이 코드로 인프라를 관리한다! IaaC (Infrastructure as a Code)입니다.
 
생성할 인프라구성들을 미리 코드로 만들어놓으면 여러번 콘솔에서 작업할 필요없이 변화되는 수만 조금 수정하여 다시 코드를 실행해 주면 되기 때문에 한결 공수를 줄일 수 있는 혁기적인 방법이죠.
 
이미 이러한 코드들을 위한 다양한 도구들이 존재하는데요
오늘은 이중에서 Terraform 에 대하여 알아보도록 하겠습니다!
 
Terraform(테라폼)이란?
한마디로 정의하자면, HashiCorp에서 제공하는 클라우드 인프라 배포 툴 입니다.
 
보통 배포툴 이라고하면 Ansible이나 Chef를 생각하시는 분들도 많으실텐데요, Ansible이 동일한 환경 배포를 도와준다고 하면 테라폼은 좀더 클라우드 환경에 초첨이 맞춰져 있습니다.
 
대표되는 퍼블릭 클라우드인 AWS, Azure, GCP 뿐만아니라 Kubernetes, Helm등 다양한 플랫폼을 지원해 주고 있습니다.
지원되는 플랫폼 -  https://www.terraform.io/docs/providers/
 
 
Terraform 설치
설치는 
해당링크를 통해 다운로드 받은 후 압축을 풀어주면 됩니다.
간단간단
 
설치 후 cmd창을 통해 확인이 가능합니다.
C:\Users\kyoun>terraform -version
Terraform v0.11.13
 
 
Your version of Terraform is out of date! The latest version
is 0.12.24. You can update by downloading from www.terraform.io/downloads.html
 
 
 
 
 
 
지난 시간에 AWS 을 가입하는법을 알아봤는데요,
AWS에 가입하자마자 제일 먼저 해야할 일은 IAM을 생성하여 사용자를 만드는 것이라 생각합니다.
(무수한 보안의 문제들로 인하여 root계정은 위험해염)
 
IAM이란?
IAM (AWS Identity and Access Management)의 약자로 AWS에서 보안을 담당하는 주요한 요소입니다.
AWS를 사용할 수 있는 사용자를 만드는 것 뿐만아니라, 각각의 사용자 및 리소스들의 권한과 같은 설정도 해줄수 있는 아주 막강하고 AWS의 대표되는 리소스입니다.
 
쉽게 설명드리자면, 보안을 철저히 해야하는 데이터센타의 경우 모든사람이 출입이 가능하지 않습니다.
보통 출입카드가 있거나 혹은 사전에 방문등록을 신청하여 임시 출입증을 부여 받습니다.
 
IAM도 이런 AWS의 보안관문이라고 생각하시면 쉬우실것같습니다.
 
IAM의 Dashboard를 한번 들어가볼까요?
 
  • IAM 콘솔화면 접속 
하단의 리소스 항목에서 IAM을 선택하셔도 괜찮고, 상단의 검색창에서 IAM으로 검색하셔도 됩니다.
 
  • IAM Dashboard

왼쪽 메뉴바에 보면 Users, Groups, Roles, Policies등의 정책들을 설정할 수 있는 항목이 있습니다.
 
자 그럼 root계정이 아닌 admin권한의 IAM 사용자를 추가하여 볼까요??
 
  • Admin Group 생성
User를 바로 생성해도 무방하지만 저는 Admin그룹을 미리 만들어 두고 나중에 사용자들을 Admin그룹에 넣어줄 예정입니다.
 
이름을 지정해준 후 admin 그룹에 맞는 정책을 연결해줍니다.
 
 
 
 
 
잘 생성된 것을 확인하실 수 있습니다!
 
 
  • Admin User 생성
왼쪽의 users 탭에서 Add user를 클릭하여줍니다.
 
 
 
사용할 User 이름을 입력한 후 Console 접속방식이기에 AWS Management Console access를 선택해줍니다. 또한 Custom password를 선택하여 임시 비밀번호를 입력해줍니다!
(아래의 Require password reset 을 체크해주면 처음 로그인할시 비밀번호 변경을 하게 됩니다.)
 
 
위에서 생성하였던 admin그룹에 쏙! 넣어줍니다.
(group을 생성하지 않았다면 가장 오른쪽에 Attach exising policies directly를 클릭하여 AdministratorAccess policy를 연결하여 줍니다.)
 
 
다음항목은 Tag를 지정해 주는 항목인데 저는 생략하였습니다 ㅎ.ㅎ 
 
잘 생성이 되었네요!
오른쪽에 Send email을 클릭하여 aws 접속정보를 email로 받아봅니다
 
 
생성한 admin IAM으로 접속해볼까요?
 
로그아웃을 해준 후 email로 받은 접속정보를 통해 콘솔화면에 접속합니다.
 
과연 로그인이 잘 될까요?
 
 
 
 
화면 상단에 admin계정으로 들어오신것을 확인하실 수 있습니다!
 
성! 공!
 
 
 
 
 
Terraform을 이용하여 AWS인프라 환경을 구축해보자  시리즈 1탄이 VPC를 구성하는 법을 알아보도록 하겠습니다.
 
환경
# local - windows 10
#Terraform version
 
PS C:\terraform> terraform -version
Terraform v0.11.13
 
#1 - AWS IAM 설정
 저희가 사용해야 할 terraform에서 aws에 접근을 하기 위하여 Key 정보가 필요한데요 
Terraform이라는 IAM을 별도로 만들고 Key를 저장해줍니다.
IAM생성은 제가 작성한 AWS 블로그 글을 참고하시면 됩니다
 
  • AWS IAM 메뉴 접속 후 사용할 Terraform User 클릭
 
 
  • 사용할 IAM 이름 선택 후 Security credentials 항목에서 Createa access key를 클릭해줍니다.
 
 
  • access_key와 secret_key 코드를 따로 저장하거나 .csv파일을 저장해줍니다.
나중에 이 키가 쓰이므로 꼭 저장해주세염!
 
 
#2 - Terraform provider
ㅈ ㅏ! 이제 key를 저장했으니 terraform 으로 가볼까요/
지난 시간에 Terraform이 무엇인지 알아보았는데요
저는 AWS위에 인프라환경을 구축할 예정이여서 Terraform이란 친구에게 AWS에서 구축을 원한다라는 정보를 알려주는게 제일 첫번째 순서가 되겠죠?
 
이를 Terraform에서는 provider라고 칭하는데요 다음과 같은 코드로 작성이 됩니다.
# provider default example
# 00.aws.tf
 
provider "aws" {
  access_key = "<AWS Access Key>"
  secret_key = "<AWS Secret Key>"
  region     = "<AWS Region>"
}
 
이를 실질적으로 적용해보면 다음과 같은 형태로 구성이 되어 집니다.
provider "aws" {
  access_key = "**********QJMA5GP***"                     <------- AWS IAM생성시 부여된 access_key
  secret_key = "**************bUZnJjDbRnbiICmY******"     <------- AWS IAM생성시 부여된 secret_key
  region     = "ap-northeast-2"                           <------- 사용할 리전
}
주의할점은 git hub같은 SCM에 업로드하실때 액세스,시크릿 키가 노출될 수 있으니 주의 하셔야 합니다.
저는 테스트 용으로 provider안에 임시로 키 설정을 해 주었지만 실제 키는 외부에 저장하는것을 추천합니다.
이러한 키 설정은 다음편에 계속!
 
 
#3 - VPC 구성
terraform과 aws를 연동해줬으니 이제 기본이 되는 VPC를 만들어봅시다.
# vpc example code
 
 resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"}
다음과 같은 형태의 sample로 코드화가 되는데요 
사용하고자 하는 vpc의 CIDR range를 지정해줍니다.
 
# VPC 구성
# 01.vpc.tf
 
resource "aws_vpc" "test" {
  cidr_block       = "10.100.0.0/16"
 
 
  tags = {
    Name = "kbseo_tf_vpc"
  }
}
tag를 이용하여서 vpc의 이름을 지정해 줄 수 있습니다.
resource같은경우 실제 구성하고자 하는 aws의 resource 타입 (여기서는 aws_vpc가 되겠죠) 뒤에오는 test는 제가 임의로 지정한 이름입니다.
다른 resource같은경우 Hashicorp 문서를 참고 바랍니다~  https://www.hashicorp.com/resources/
 
다음과 같이 vpc를 구성 해 준 뒤 대망의 terraform을 돌려돌려돌려볼까요?
 
 
#4 - terraform init
terraform init이란 선언된 프로바이더를 보고 필요한 플러그인등을 가져옵니다
 
 
PS C:\terraform> terraform init
 
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (2.59.0)...
 
알맞은 플러그인들은 가져온것 같네요!
init후 terraform 버전을 확인해 보면 프로바이더 버젼도 함께 출력되는것을 보실 수 있습니다.
PS C:\terraform> terraform -version
Terraform v0.11.13
+ provider.aws v2.59.0
 
프로바이더의 플러그인을 잘 가져왔으니 이제 terraform을 실행해봅니다.
 
 
#5 - terraform plan / terraform apply
terraform plan같은경우 현재 저희가 뚝딱뚝딱 코드로 만들어 놓은 리소스들을 실제로 프로바이더(aws)에 적용했을 시 테라폼이 어떠한 작업을 수행할 지 보여줍니다.
apply하기 전에 미리 확인하면 좋겠죠 ^.~
 
$ terraform plan
PS C:\terraform> terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
 
 
 
 
------------------------------------------------------------------------
 
 
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 
 
Terraform will perform the following actions:
 
 
  + aws_vpc.test
      id:                               <computed>
      arn:                              <computed>
      assign_generated_ipv6_cidr_block: "false"
      cidr_block:                       "10.100.0.0/16"
      default_route_table_id:           <computed>
      default_security_group_id:        <computed>
      dhcp_options_id:                  <computed>
      enable_classiclink:               <computed>
      enable_classiclink_dns_support:   <computed>
      enable_dns_hostnames:             <computed>
      enable_dns_support:               "true"
      ipv6_association_id:              <computed>
      ipv6_cidr_block:                  <computed>
      main_route_table_id:              <computed>
      owner_id:                         <computed>
      tags.%:                           "1"
      tags.Name:                        "kbseo_tf_vpc"
 
 
 
 
Plan: 1 to add, 0 to change, 0 to destroy.
 
 
------------------------------------------------------------------------
 
 
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
실제 테라폼을 구동했을 시 적용되는것을 잘 보여줍니다!
 
자 그럼 이제 적용해볼차례
 
 
$ terraform apply
PS C:\terraform> terraform apply
 
 
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 
 
Terraform will perform the following actions:
 
 
  + aws_vpc.main
      id:                               <computed>
      arn:                              <computed>
      assign_generated_ipv6_cidr_block: "false"
      cidr_block:                       "10.100.0.0/16"
      default_network_acl_id:           <computed>
      default_route_table_id:           <computed>
      default_security_group_id:        <computed>
      dhcp_options_id:                  <computed>
      enable_classiclink:               <computed>
      enable_classiclink_dns_support:   <computed>
      enable_dns_hostnames:             <computed>
      enable_dns_support:               "true"
      instance_tenancy:                 "dedicated"
      ipv6_association_id:              <computed>
      ipv6_cidr_block:                  <computed>
      main_route_table_id:              <computed>
      owner_id:                         <computed>
      tags.%:                           "1"
      tags.Name:                        "kbseo_tf_vpc"
 
 
 
 
Plan: 1 to add, 0 to change, 0 to destroy.
 
 
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
 
 
aws_vpc.main: Creating...
  arn:                              "" => "<computed>"
  assign_generated_ipv6_cidr_block: "" => "false"
  cidr_block:                       "" => "10.100.0.0/16"
  default_network_acl_id:           "" => "<computed>"
  default_route_table_id:           "" => "<computed>"
  default_security_group_id:        "" => "<computed>"
  dhcp_options_id:                  "" => "<computed>"
  enable_classiclink:               "" => "<computed>"
  enable_classiclink_dns_support:   "" => "<computed>"
  enable_dns_hostnames:             "" => "<computed>"
  enable_dns_support:               "" => "true"
  instance_tenancy:                 "" => "dedicated"
  ipv6_association_id:              "" => "<computed>"
  ipv6_cidr_block:                  "" => "<computed>"
  main_route_table_id:              "" => "<computed>"
  owner_id:                         "" => "<computed>"
  tags.%:                           "" => "1"
  tags.Name:                        "" => "kbseo_tf_vpc"
aws_vpc.main: Creation complete after 2s (ID: vpc-0366a37927f68d179)
 
 
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
 
잘 생성된 것 같아보입니다!
콘솔로 확인해볼까요?
 
 
잘 만들어졌습니다!
 
오늘은 간단하게 terraform 을 이용하여 aws상 vpc를 구성하는것을 살펴보았는데요
사실상 aws상에서 네트워크를 구성하려면 vpc뿐만아니라 subnet, routing table등등 설정해줘야할 사항이 많은데요..
매번 IP대역들을 각각의 tf파일에 적어주면 여러번 구성할때마다 헷갈리실거예요..
(저만 헷갈리시는거 아니죠ㅜㅜ?)
 
그렇기에 이렇게 ip 대역들 같이 매번 변하는 수들을 따로 모아서 tf파일로 관리하는데요
다음시간에는 좀 더 효율적으로 테라폼을 관리하는 법에 대해 알아보겠습니다!
 
 
 
 
도커를 설치하고 컨테이너를 실행해봤으니 이제는 도커 이미지를 만들고 서버에 배포해볼 차례!
도커 개념에서도 다뤄봤듯이, 도커는 도커 파일을 가지고 도커 이미지를 만들게 되는데요, 
다시 한번 말씀드리자면, Docker File이란 Docker Image를 만들기 위한 여러가지 명렁어의 집합입니다.
프로페셔널한 엔지니어라면 뚝딱뚝딱 Dockerfile을 만들 수 있지만 
저는 초보자이기 때문에 서버에 명령어를 입력하고 버그를 잡아가면서 Dockerfile을 한 땀 한 땀 만듭니다.
 
 
만약에 여러분이 우분투 서버에서 nginx를 설치해서 실행한다고 가정했을 시 순서는 다음과 같습니다.
  1. ubuntu 설치
  2. 패키지 업데이트
  3. nginx 설치
  4. 경로설정 (필요한 경우)
먼저 리눅스 서버에서 한줄한줄 테스트를 해봅니다
## 1. ubuntu 설치 & 2. 패키지 업데이트
# 테스트 ubuntu 서버를 사용하였기 때문에 패키지 업데이트를 먼저 합니다.
 
## 1. ubuntu 설치 & 2. 패키지 업데이트
# 테스트 ubuntu 서버를 사용하였기 때문에 패키지 업데이트를 먼저 합니다.

kbseo@KB-SEO:~$ sudo apt-get update
[sudo] password for kbseo:
Hit:1 http://mirror.kakao.com/ubuntu bionic InRelease
Get:2 http://mirror.kakao.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:3 http://mirror.kakao.com/ubuntu bionic-backports InRelease [74.6 kB]
Get:4 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:5 http://mirror.kakao.com/ubuntu bionic-updates/main amd64 Packages [872 kB]
Get:6 http://mirror.kakao.com/ubuntu bionic-updates/main Translation-en [303 kB]
Get:7 http://mirror.kakao.com/ubuntu bionic-updates/restricted amd64 Packages [32.9 kB]
Get:8 http://mirror.kakao.com/ubuntu bionic-updates/restricted Translation-en [8468 B]
Get:9 http://mirror.kakao.com/ubuntu bionic-updates/universe amd64 Packages [1055 kB]
Get:10 http://mirror.kakao.com/ubuntu bionic-updates/universe Translation-en [326 kB]
Get:11 http://mirror.kakao.com/ubuntu bionic-updates/multiverse amd64 Packages [10.1 kB]
Get:12 http://mirror.kakao.com/ubuntu bionic-updates/multiverse Translation-en [4636 B]
Get:13 http://mirror.kakao.com/ubuntu bionic-backports/universe amd64 Packages [4028 B]
Get:14 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [651 kB]
Get:15 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [211 kB]
Get:16 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [23.8 kB]
Get:17 http://security.ubuntu.com/ubuntu bionic-security/restricted Translation-en [6528 B]
Get:18 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [648 kB]
Get:19 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [215 kB]
Get:20 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [6756 B]
Get:21 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [2700 B]
Fetched 4634 kB in 6s (739 kB/s)
Reading package lists... Done
kbseo@KB-SEO:~$

## 3. nginx 설치
kbseo@KB-SEO:~$ sudo apt-get install nginx
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libnginx-mod-http-geoip
  libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6
  libxpm4 nginx-common nginx-core
Suggested packages:
  libgd-tools fcgiwrap nginx-doc ssl-cert
The following NEW packages will be installed:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0 libjpeg-turbo8 libjpeg8 libnginx-mod-http-geoip
  libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6
  libxpm4 nginx nginx-common nginx-core
0 upgraded, 18 newly installed, 0 to remove and 239 not upgraded.
Need to get 2461 kB of archives.
After this operation, 8210 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
...
...
#이하 생략
#설치 확인
kbseo@KB-SEO:~$ nginx -v
nginx version: nginx/1.14.0 (Ubuntu)
kbseo@KB-SEO:~$

# 설치파일 경로
kbseo@KB-SEO:/etc/nginx$ pwd
/etc/nginx
 
 
여기서 잠깐
  • 저희는 nginx를 패키지를 통하여 설치 하였기에 Default directory가 /etc/nginx 아래에 위치하게 됩니다.
  • 직접 compile한 경우에 경로는 /usr/local/nginx/conf 혹은 /use/local/etc/nginx 에 위치하고 있습니다.
  • 그래도 경로가 없다 한다면 다음의 명령어를 통해 찾을 수 있습니다.
kbseo@KB-SEO:/etc/nginx$ sudo find / -name nginx.conf
/etc/nginx/nginx.conf

  1. 경로설정 (필요한 경우)
kbseo@KB-SEO:/etc/nginx$ ls
conf.d fastcgi_params koi-win modules-available nginx.conf scgi_params sites-enabled uwsgi_params
fastcgi.conf koi-utf mime.types modules-enabled proxy_params sites-available snippets win-utf

# 기본적인 환경 설정 파일 정보는 sites-available/default 이곳에 있습니다.
# 따라서 웹서버의 루트 디렉토리 변경 등의 작업이 필요하다면 이곳에 들어가 작업하시면 됩니다.

kbseo@KB-SEO:/etc/nginx$ vim sites-available/default
 
설정하실때 세미콜론(;) 잊지 말아쥬세염
저는 테스트이기 때문에 따로 경로 설정은 안하고 Default로 두었습니다.
# index.html 를 만든 후 찍어 봅니다.
kbseo@KB-SEO:/var/www/html$ sudo service nginx restart
* Restarting nginx nginx [ OK ]
kbseo@KB-SEO:/var/www/html$
kbseo@KB-SEO:/var/www/html$ curl 127.0.0.1
Hello KB

이제는 이런 한땀한땀 구축한 명령어를 토대로 docker file을 만들어 보겠습니다.

  1. ubuntu 설치
  2. 패키지 업데이트 apt-get update
  3. nginx 설치 apt-get install nginx
  4. 경로설정 (필요한 경우) cd /etc/nginx
 
위와 같은 순서로 한줄한줄 수작업을 해 주었는데 Docker file은 어떨까요?
FROM ubuntu:14.04
MAINTAINER Dongbin Na "kbseo@osci.kr"
RUN apt-get update
RUN apt-get install -y nginx
WORKDIR /etc/nginx
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80

 

 
 
docker file이 거의 흡사하게 작성된 것을 보실 수 있습니다. 아마 도커파일에 있는 내용들이 생소하실 여러분(저를 포함)을 위해 하나하나 뜯어 보도록 할까요?
 
1. FROM ubuntu:14.04 -> 기반으로 할 이미지를 가져옵니다. 여기에서는 ubuntu 14.04버전의 이미지를 가져오겠습니다.
2. MAINTAINER Dongbin Na "kbseo@osci.kr" -> 작성자의 정보를 기입해줍니다.
3. RUN apt-get update -> RUN이라는 명령어를 통하여 쉘 스크립트를 실행하여 줍니다.
4. RUN apt-get install -y nginx -> 도커 빌드 중에는 키보드를 입력할 수 없기에 [-y] 옵션을 넣어줍니다.
5. WORKDIR /etc/nginx -> 이후 CMD 명령어가 실행 할 경로로 먼저 이동을 해 줍니다.
6. CMD ["nginx", "-g", "daemon off;"] -> nginx를 백그라운드로 실행합니다

 

7. EXPOSE 80 -> 80번 포트를 오픈하여 웹서버에 정상적으로 접근할 수 있게 합니다.
 
 

 

아직까지 Dockerfile 명령어들이 익숙치 않으시죠? 아니라고 해도 명령어들은 좀더 나눠서 알아보겠습니다.
 
명렁어
내용
예시
 
FROM
- 베이스 이미지를 지정해줍니다.
FROM <image>:<tag>
FROM ubuntu:14.04
-> 베이스 이미지는 반드시 지정해줘야하며, 버전정보는 latest보다는 구체적인 버전을 지정해주는것이 좋습니다.
RUN
- 직접적으로 쉘 스크립트 내에서 실행 될 명령어 앞에 적어줍니다.
RUN <command>
RUN apt-get update
-> 실질적으로 가장 많이 쓰이는 명령어 입니다
CMD
- 도커가 실행될 때 실행할 명령어를 정의해줍니다.
CMD ["executable", "param", "param"]
CMD ["nginx", "-g", "daemon off;"]
-> 도커 빌드시에는 실행되지 않으며, 여러개의 CMD 명령어가 존재할 경우 가장 마지막 명령어만 실행 됩니다. CMD nginx 라고 입력하면 nginx 서버를 구동시키게 됩니다.
WORKDIR
- 이후 명령어가 작업할 디렉토리로 이동합니다
WORKDIR /path
WORKDIR /etc/nginx
-> 명령어(RUN, CMD ) 등이 실행될 디렉토리를 설정합니다. 각 명령어는 줄마다 초기화가 되기 때문에 'RUN cd /path' 로 경로를 잡아줘도 다음줄에선 다시 위치가 초기화가 됩니다. 같은 디렉토리에서 계속 작업하기 위하여 WORKDIR을 사용해줍니다.
COPY
- 파일이나 디렉토리를 이미지로 복사합니다
COPY <src> <dst>
COPY . /usr/src/app
-> 일반적으로 소스를 복사하는데 사용합니다
ADD
- COPY와 비슷하게 복사를 위해 사용합니다
ADD <src> <dst>
ADD . /usr/src/app
-> COPY명령어와 비슷하게 소스를 복사하는데 사용하지만 차이점은 ADD같은경우 압축파일이 있을 경우 자동으로 압축을 해제하면서 복사됩니다.
EXPOSE
- 공개 하고자 하는 포트를 지정해줍니다
EXPOSE <port>
EXPOSE 80

 

-> 호스트와 연결해줄 포트를 지정해주며, 여러개의 포트를 지정할 수 있습니다.
 
이 밖에 사용되는 ENV ,VOLUME 같은 명령어는 공식문서를 참고 바랍니다

 

 
 
 

Dockerfile을 만들었으니 Build를 해봅시다.

docker build --force-rm --tag mynginx:0.1 .
  • --force-rm : 기존에 존재하는 image를 삭제합니다.
  • --tag : 태그를 설정해줍니다.
 
[kbseo@ip-172-20-1-221 docker]$ docker build --force-rm --tag mynginx:0.1 .
Sending build context to Docker daemon 2.048kB
Step 1/7 : FROM ubuntu:14.0414.04: Pulling from library/ubuntu
2e6e20c8e2e6: Pull complete
30bb187ac3fc: Pull complete
b7a5bcc4a58a: Pull complete
Digest: sha256:ffc76f71dd8be8c9e222d420dc96901a07b61616689a44c7b3ef6a10b7213de4
Status: Downloaded newer image for ubuntu:14.04
---> 6e4f1fe62ff1
Step 2/7 : MAINTAINER Dongbin Na "kbseo@osci.kr"
---> Running in 224535a7dd96
Removing intermediate container 224535a7dd96
---> dc0f4b41cf96
Step 3/7 : RUN apt-get update
---> Running in 1e6d817f7aa0
...
...
Removing intermediate container 1e6d817f7aa0
---> bf2a670332b6
Step 4/7 : RUN apt-get install -y nginx
---> Running in b5fe65990ed8
...
...
Removing intermediate container b5fe65990ed8
---> 6664b9edcc36
Step 5/7 : WORKDIR /etc/nginx
---> Running in 34f5b2fe1f42
Removing intermediate container 34f5b2fe1f42
---> bc81d2ba24e1
Step 6/7 : CMD ["nginx", "-g", "daemon off;"]
---> Running in 45d49d210fea
Removing intermediate container 45d49d210fea
---> 44591f5b5a0c
Step 7/7 : EXPOSE 80
---> Running in b98221c6597d
Removing intermediate container b98221c6597d
---> 747275175211
Successfully built 747275175211
Successfully tagged mynginx:0.1
[kbseo@ip-172-20-1-221 docker]$

# 이미지확인
[kbseo@ip-172-20-1-221 docker]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mynginx 0.1 747275175211 12 minutes ago 231MB
registry latest 708bc6af7e5e 7 weeks ago 25.8MB
ubuntu 14.04 6e4f1fe62ff1 2 months ago 197MB
localhost:5000/hello-world latest fce289e99eb9 14 months ago 1.84kB
hello-world latest fce289e99eb9 14 months ago 1.84kB
[kbseo@ip-172-20-1-221 docker]$

 

 
 
빌드가 완료되어 Docker Image가 만들어진 것을 확인할 수 있는데요 이 빌드가 되는 과정들도 또 하나하나 살펴보도록 하겠습니다.
빌드과정을 요약하면 다음과 같습니다.
Sending build context to Docker daemon 2.048kB   <--- [1]
Step 1/7 : FROM ubuntu:14.04                     <--- [2] 
14.04: Pulling from library/ubuntu               <--- [3]
---> 6e4f1fe62ff1                                <--- [4]
Step 2/7 : MAINTAINER Dongbin Na "kbseo@osci.kr" <--- [5]
---> Running in 224535a7dd96                     <--- [6]
Removing intermediate container 224535a7dd96     <--- [7]
---> dc0f4b41cf96                                <--- [8]
Step 3/7 : RUN apt-get update                    <--- [9]
---> Running in 1e6d817f7aa0
...
Successfully built 747275175211                  <--- [10]

 

[1] Sending build context to Docker daemon 2.048kB
도커는 서버 클라이언트 구조이기 때문에 작업할 도커파일들(build context)을 도커서버(daemon)으로 전송해줍니다.

 

[2] Step 1/7 : FROM ubuntu:14.04
빌드할 도커파일의 제일 윗줄부터 한줄한줄 실행하여 줍니다.

 

[3] 14.04: Pulling from library/ubuntu
ubuntu라는 이미지를 repository에서 다운받는 작업을 합니다 기본적으로 DockerHub Repository를 사용하고 있으며 사용자가 별도의 저장소를 지정할 수 있습니다.

 

[4] ---> 6e4f1fe62ff1
다운받은 ubuntu 이미지의 ID를 출력해줍니다.

 

[5] Step 2/7 : MAINTAINER Dongbin Na "kbseo@osci.kr"
도커파일의 두번째 명령어를 실행해줍니다.

 

[6] ---> Running in 224535a7dd96
도커는 이미지 형태로 저장하기 때문에 바로위에서 실행한 우분투 이미지 '6e4f1fe62ff1'를 기반으로 임시 컨테이너 '224535a7dd96' 를 만듭니다.

 

[7],[8]
Removing intermediate container 224535a7dd96
---> dc0f4b41cf96
임시로 실행했던 컨테이너 '224535a7dd96'를 삭제해주고 새로운 이미지 'dc0f4b41cf96'를 만듭니다.

 

[9] Step 3/7 : RUN apt-get update
도커파일에 작성하였던 다음줄의 명령어를 실행해줍니다. 이전 단계 에서처럼 _전에 만들어진 이미지를 기반으로 임시 컨테이너를 만들어 명령어를 실행하고 이를 또 다른 이미지로 저장을 한 후 임시 컨테이너는 삭제_하여줍니다. 이러한 과정을 도커파일의 마지막 명령줄까지 반복합니다.

 

[10] Successfully built 747275175211
최종적으로 만들어진 이미지ID를 멋지게 출력해줍니다.

 

좀 전에 빌드했던 도커파일을 다시 빌드하게 되면 처음 빌드했을 때 보다 훨씬 빨라지게 되는데요 그 이유는, 명령어를 실행할 때 이미지 위에 레이어를 추가하는 형태로 저장을 하게 되고 재 빌드를 하게 되면 기존에 저장된 이미지를 그대로 캐시처럼 사용하여 빌드 하기 때문입니다. (변경된 사항이 없다면)
 
# 재빌드
Sending build context to Docker daemon 2.048kB
Step 1/7 : FROM ubuntu:14.04
---> 6e4f1fe62ff1
Step 2/7 : MAINTAINER Dongbin Na "kbseo@osci.kr"
---> Using cache
---> dc0f4b41cf96
Step 3/7 : RUN apt-get update
---> Using cache
---> bf2a670332b6
Step 4/7 : RUN apt-get install -y nginx
---> Using cache
---> 6664b9edcc36
Step 5/7 : WORKDIR /etc/nginx
---> Using cache
---> bc81d2ba24e1
Step 6/7 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> 44591f5b5a0c
Step 7/7 : EXPOSE 80
---> Using cache
---> 747275175211
Successfully built 747275175211
 
이러한 도커빌드 원리를 이해하고 있으면 도커파일을 만들 때 효과적으로 만드실 수 있습니다.
참고로 명렁어를 주르륵 나열하기보단 최대한 간결하고 '&&' 명령어를 이용해 줄여서 적어주는것이 좋습니다! (스토리지 엔진에 따라 이미지 개수가 제한되는 경우도 있기때문)

 

 
 
 
###빌드한 이미지는 각 서버에 어떻게 배포할까요?
도커는 이미지를 각각의 서버에 복사하는 방법 대신 저장소(Registry)를 이용합니다.
 
 
여기서 이미지를 저장소에 업로드할때 'puch' 명령어를 사용하고, 각 서버에서 저장소에 올려져있는 이미지를 가져올때 'pull'이라는 명령어를 사용합니다.
 
저번시간에 tag에 대하여 스르륵 지나갔었는데 이미지 이야기를 하는김에 같이 다뤄보도록 하겠습니다.
 

이미지 태그에 관하여

'docker tag <옵션> <이미지 이름>:<태그> <저장소 주소, 사용자명>/<이미지이름>:<태그>' 굉장히 복잡해 보입니다...

 

저장소 주소는 기본적으로 Docker hub를 바라보고 있고, 사용자 ID를 지정해주지 않으면 기본으로 library를 사용합니다.
즉, '<저장소 주소, 사용자명>/<이미지이름>:<태그>'는 docker.io/library/nginx = library/nginx = nginx 이렇게 추릴수도 있습니다.
이미지 이름 변경
'docker tag <reponame>:<old_name> <new_reponame>:<new_name> -> 이름을 변경한다기 보다는 복제라고 보는게 더 맞습니다. 예시) 'docker tag mynginx:0.2 kbseonginx:0.1'
#before[kbseo@ip-172-20-1-221 docker]$ docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmynginx 0.1 747275175211 25 hours ago 231MBmynginx 0.2 747275175211 25 hours ago 231MB
#afterREPOSITORY TAG IMAGE ID CREATED SIZEkbseonginx 0.1 747275175211 25 hours ago 231MBmynginx 0.1 747275175211 25 hours ago 231MBmynginx 0.2 747275175211 25 hours ago 231MB
이렇게 해서 이번 시간에는 Docker File과 Image에 대하여 알아보았는데요
다음번에는 실질적으로 사용하고 있는 application을 어떻게 Dockerized 할 것인가
라는 주제로 다시 찾아뵙도록 하겠습니다.
뿅!
 
 
nginx docker image를 여 registry로 부터 image pull, run, 그리고 삭제하는 과정에 대해 기술 
 
안녕하세요 ^^
저번시간에 설치만 해서 너무 간질간질 하셨을 여러분을 위해
지난 글에 이어서 Docker 기본 명령어에 대해 알아보는 시간을 가지도록 하겠습니다.
 

1. Image 가져오기

: 기본 개념에서와 같이 도커는 저장소(registry)에서 이미지를 가져와 사용을 합니다
$ docker pull nginx:latest
# docker images 명령어를 통해 현재 가지고 있는 이미지 확인
[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE

# docker login
[kbseo@ip-172-20-1-221 ~]$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: kbseo
Password:
WARNING! Your password will be stored unencrypted in /home1/kbseo/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
 
이미지를 땡겨 봅시다
# tag를 지정해주지 않으면 default로 latest 버전을 가져옵니다.
# tag를 지정할 경우
# docker pull nginx:latest
# 위의 명령어 대로 pull 가능

[kbseo@ip-172-20-1-221 ~]$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
bc51dd8edc1b: Pull complete
66ba67045f57: Pull complete
bf317aa10aa5: Pull complete
Digest: sha256:ad5552c786f128e389a0263104ae39f3d3c7895579d45ae716f528185b36bc6f
Status: Downloaded newer image for nginx:latest
[kbseo@ip-172-20-1-221 ~]$

# 이미지 확인
[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2073e0bcb60e 3 weeks ago 127MB
[kbseo@ip-172-20-1-221 ~]$
 
이미지를 가져왔으니 이제 실행시켜봐야죠!
 

2. Run Container

# docker ps 라는 명령어로 현재 실행중인 컨테이너를 확인합니다.
# docker ps -a -> 중지된 컨테이너까지 모두 출력

[kbseo@ip-172-20-1-221 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
실행중인 컨테이너가 없네요
 
# docker run 이라는 명령어로 컨테이너를 실행시켜줍니다.
# docker run <옵션> <이미지 이름> <실행할 파일>

[kbseo@ip-172-20-1-221 ~]$ docker run -it -d -p 8080:80 --name=nginx nginx:latest
57c8f50ce8c565e7b8fcfbe3a730b4be9c7c0221606ee0ba7dc22295d1b8ae04

# 옵션 -i(interactive), -t(Pseudo-tty) -> Bash Shell에 입력 및 출력을 할 수 있습니다.
# 옵션 --name -> 컨테이너의 이름을 지정해 줍니다.
# 옵션 -d -> daemonized
# 옵션 -p -> 포트포워딩

[kbseo@ip-172-20-1-221 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57c8f50ce8c5 nginx:latest "nginx -g 'daemon of…" 4 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp nginx
[kbseo@ip-172-20-1-221 ~]$

[kbseo@ip-172-20-1-221 ~]$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[kbseo@ip-172-20-1-221 ~]$

잘 뜨네요. 기쁩니다.
 
 
 
 
컨테이너를 실행했으니 내부로 들어가 봅시다.

3. Container 내부탐험

$ docker exec
# 내부장벽진입
[kbseo@ip-172-20-1-221 ~]$ docker exec -it nginx /bin/bash
root@57c8f50ce8c5:/#

# 진입완료
# 컨테이너의 hostname을 알아봅시다
root@57c8f50ce8c5:/# hostname
57c8f50ce8c5

root@57c8f50ce8c5:/# cat /etc/issue
Debian GNU/Linux 10 \n \l

root@57c8f50ce8c5:/#

# Shell을 빠져나오려면 Ctrl + D 혹은 exit를 입력합니다.

# exit로 나왔을 경우 container 도 쉘 종료메세지(exit 0)을 받고 자연스럽게 종료 되기때문에 
# docker start [컨테이더 ID ] 명령어로 재시작 혹은 ctrl+ p 혹은 ctrl + q 로 실행을 유지한 채 
# 터미널로 빠져 나올 수 있습니다.
 

4. Image 삭제

: 보통은 이미지를 삭제하기 전 컨테이너를 먼저 삭제한 후 진행됩니다.
# docker rm 명령어를 통해 삭제합니다
# 컨테이너 삭제
[kbseo@ip-172-20-1-221 ~]$ docker rm nginx
Error response from daemon: You cannot remove a running container 57c8f50ce8c565e7b8fcfbe3a730b4be9c7c0221606ee0ba7dc22295d1b8ae04. Stop the container before attempting removal or force remove

# 어라? 삭제가 안되네요
# 먼저 중지를 해줍니다.

# I will find you and I will kill you...

[kbseo@ip-172-20-1-221 ~]$ docker kill nginx
nginx

# 다시삭제를 해봅니다.
[kbseo@ip-172-20-1-221 ~]$ docker rm nginx
nginx
[kbseo@ip-172-20-1-221 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[kbseo@ip-172-20-1-221 ~]$

# 잘 삭제가 되네요
 
이미지도 지워버립시다.
# docker rmi 명령어를 통해 이미지를 삭제해줍니다.

[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 2073e0bcb60e 3 weeks ago 127MB
[kbseo@ip-172-20-1-221 ~]$

# $ docker rmi nginx:latest 혹은 $ docker rmi [ 이미지 ID ]

[kbseo@ip-172-20-1-221 ~]$ docker rmi nginx:latest
Untagged: nginx:latest
Untagged: nginx@sha256:ad5552c786f128e389a0263104ae39f3d3c7895579d45ae716f528185b36bc6f
Deleted: sha256:2073e0bcb60ee98548d313ead5eacbfe16d9054f8800a32bedd859922a99a6e1
Deleted: sha256:a3136fbf38691346715cac8360bcdfca0fff812cede416469653670f04e2cab0
Deleted: sha256:99360ffcb2da18fd9ede194efaf5d4b90e7aee99f45737e918113e6833dcf278
Deleted: sha256:488dfecc21b1bc607e09368d2791cb784cf8c4ec5c05d2952b045b3e0f8cc01e
[kbseo@ip-172-20-1-221 ~]$
[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
컨테이너를 삭제하기 전 이미지를 삭제할 경우 -f옵션으로 한꺼번에 삭제할 수 있습니다.
$ docker rmi -f [이미지 ID] 
> 컨테이너도 강제삭제 
 
 
이렇게 끝내면 너무 아쉬우니 부가적으로 이미지를 저장할때 aws s3로 저장하는 방법도 슬쩍 소개해 드리겠습니다.
aws가 좋아서 그런거는 아닙니다.

+ AWS S3에 컨테이너 이미지 저장

  • Docker registry 이미지를 가져옵니다.
# docker pull registry:latest
[kbseo@ip-172-20-1-221 ~]$ docker pull registry:latest
latest: Pulling from library/registry
486039affc0a: Pull complete
ba51a3b098e6: Pull complete
8bb4c43d6c8e: Pull complete
6f5f453e5f2d: Pull complete
42bc10b72f42: Pull complete
Digest: sha256:7d081088e4bfd632a88e3f3bcd9e007ef44a796fddfe3261407a3f9f04abe1e7
Status: Downloaded newer image for registry:latest
[kbseo@ip-172-20-1-221 ~]$

 

  • 이미지를 컨테이너로 실행해줍니다.
# 다운받은 이미지 Run
[kbseo@ip-172-20-1-221 ~]$ docker run -d -p 5000:5000 --restart=always --name docker-registry \
> -e REGISTRY_STORAGE=s3 \
> -e REGISTRY_STORAGE_S3_BUCKET=kbseo-s3 \
> -e REGISTRY_STORAGE_S3_ACCESSKEY=AKIAJMYYWQIA******* \
> -e REGISTRY_STORAGE_S3_SECRETKEY=YTOwsm0lDgghwjRHtR************ \
> -e REGISTRY_STORAGE_S3_REGION=ap-northeast-2 \
> registry
274a07c0c008d866e44215eb4b3626448e5ef11fa573acd69ecb3e000ebde7b2

[kbseo@ip-172-20-1-221 ~]$

# docker run -d -p 5000:5000 --restart=always --name docker-registr -> s3-registry 이미지 이름 지정 후 registry 기본포트 5000번으로 실행해줍니다
# -e SETTINGS_FLAVOR=s3 -> SETTINGS_FLAVOR는 s3로 설정해줍니다.
# -e AWS_BUCKET=kbseo-s3 -> 저장할 버킷이름을 지정해주세요
# -e STORAGE_PATH=/registry -> 저장될 경로입니다.
# -e AWS_KEY=AKIAJMYYWQIA******* -> IAM 혹은 루트계정의 Access Key를 입력해주세요
# -e AWS_SECRET=YTOwsm0lDgghwjRHtR************ -> IAM 혹은 루트계정의 Secret Key를 입력해주세요

docker run -d -p 5000:5000 --restart=always --name docker-registry \
-e REGISTRY_STORAGE=s3 \
-e REGISTRY_STORAGE_S3_BUCKET=kbseo-s3 \
-e REGISTRY_STORAGE_S3_ACCESSKEY=AKIAJMYYWQIA****** \
-e REGISTRY_STORAGE_S3_SECRETKEY=YTOwsm0lDgghwjRHtR************ \
-e REGISTRY_STORAGE_S3_REGION=ap-northeast-2 \
registry
 
  • 이제 s3로 푸시해볼 차례입니다.
# 어떤 이미지를 푸시해볼까....
[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry latest 708bc6af7e5e 4 weeks ago 25.8MB
[kbseo@ip-172-20-1-221 ~]$

# 음.. 이미지를 다 지워서 push할 이미지가 없네요
# 만만한 hello-world 이미지를 받아봅니다.

[kbseo@ip-172-20-1-221 ~]$ docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:fc6a51919cfeb2e6763f62b6d9e8815acbf7cd2e476ea353743570610737b752
Status: Downloaded newer image for hello-world:latest
[kbseo@ip-172-20-1-221 ~]$
[kbseo@ip-172-20-1-221 ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry latest 708bc6af7e5e 4 weeks ago 25.8MB
hello-world latest fce289e99eb9 14 months ago 1.84kB
localhost:5000/hello-world latest fce289e99eb9 14 months ago 1.84kB


# tag를 지정해줍니다
# tag에 대해선 다음시간에 좀 더 자세히 다뤄보도록 하겠습니다.
[kbseo@ip-172-20-1-221 ~]$ docker tag hello-world localhost:5000/hello-world

# registry가 잘 돌아가고있네요
[kbseo@ip-172-20-1-221 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
274a07c0c008 registry "/entrypoint.sh /etc…" 7 seconds ago Up 6 seconds 0.0.0.0:5000->5000/tcp docker-registry
[kbseo@ip-172-20-1-221 ~]$



# s3에 올려볼 차례
[kbseo@ip-172-20-1-221 ~]$ docker push localhost:5000/hello-world
The push refers to repository [localhost:5000/hello-world]
af0b15c8625b: Pushed
latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524
[kbseo@ip-172-20-1-221 ~]$

 

  • 확인
잘 올라갔는지 s3로 가봅시다 총총총
요기 올라와져있네여
 
사실상 Code →  Docker file → Docker Image 형태이기 때문에  이러한 과정에서 수정사항이 있으면 Docker file을 재작성 후 재빌드하고 이를 다시 Image화 하야하는데
천리길도 한걸음부터 라는 말이 있듯이!
이러한 과정은 다음시간에 이어서 소개해 드리겠습니다.

 

 
기존에 테스트용으로 사용하던 서버위에 설치
서버 환경 : Amazon Linux 2 
서버 스펙 : t3.micro
안녕하세요 저번시간에 Container와 Docker에 대해서 간략하게 알아보는 시간을 가졌는데요
 
지난 시간 글 https://kbseo.tistory.com/7 [Container 시리즈] 00. Container/ Docker란 뭔가요?
아무래도 엔지니어분들은 직접 명령어를 쳐야 몸이 풀리기때문에 
도커 설치하는 법 부터 가져왔습니다!
자 한번 설치를 시작해볼까요???

 

 

1. 테스트 서버를 오랜만에 접속해서 업데이트를 먼저 해줍니다.

$ sudo yum -y upgrade
[ec2-user@ip-172-20-1-221 ~]$ sudo yum -y upgrade
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core | 2.4 kB 00:00:00
amzn2extra-docker | 1.3 kB 00:00:00
Resolving Dependencies
--> Running transaction check
---> Package amazon-ssm-agent.x86_64 0:2.3.662.0-1.amzn2 will be updated
---> Package amazon-ssm-agent.x86_64 0:2.3.714.0-1.amzn2 will be an update
---> Package at.x86_64 0:3.1.13-23.amzn2 will be updated

...

sysstat.x86_64 0:10.1.5-18.amzn2.0.1 systemd.x86_64 0:219-57.amzn2.0.12
systemd-libs.x86_64 0:219-57.amzn2.0.12 systemd-sysv.x86_64 0:219-57.amzn2.0.12
systemtap-runtime.x86_64 0:4.2-1.amzn2.0.1 tcpdump.x86_64 14:4.9.2-4.amzn2.1
yum.noarch 0:3.4.3-158.amzn2.0.3

Replaced:
kpatch.noarch 0:0.4.0-3.amzn2 rpm-python.x86_64 0:4.11.3-25.amzn2.0.3

Complete!
 

2. Docker를 설치해볼차례!

$ sudo amazon-linux-extras install -y docker
[ec2-user@ip-172-20-1-221 ~]$ sudo amazon-linux-extras install -y docker
Installing docker
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Cleaning repos: amzn2-core amzn2extra-docker
10 metadata files removed
4 sqlite files removed
0 metadata files removed
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core | 2.4 kB 00:00:00
amzn2extra-docker | 1.3 kB 00:00:00
(1/4): amzn2-core/2/x86_64/updateinfo | 187 kB 00:00:00
(2/4): amzn2-core/2/x86_64/group_gz | 2.5 kB 00:00:00

...

===================================================================================================================================
Package Arch Version Repository Size
===================================================================================================================================
Installing:
docker x86_64 18.09.9ce-2.amzn2 amzn2extra-docker 30 M
Installing for dependencies:
containerd x86_64 1.2.6-1.amzn2 amzn2extra-docker 20 M
libcgroup x86_64 0.41-21.amzn2 amzn2-core 66 k
pigz x86_64 2.3.4-1.amzn2.0.1 amzn2-core 81 k
runc x86_64 1.0.0-0.1.20190510.git2b18fe1.amzn2 amzn2extra-docker 2.0 M

Transaction Summary
===================================================================================================================================
Install 1 Package (+4 Dependent packages)

Total download size: 51 M
Installed size: 214 M
Downloading packages:
(1/5): libcgroup-0.41-21.amzn2.x86_64.rpm | 66 kB 00:00:00
(2/5): pigz-2.3.4-1.amzn2.0.1.x86_64.rpm | 81 kB 00:00:00
(3/5): containerd-1.2.6-1.amzn2.x86_64.rpm | 20 MB 00:00:00
(4/5): runc-1.0.0-0.1.20190510.git2b18fe1.amzn2.x86_64.rpm | 2.0 MB 00:00:00
(5/5): docker-18.09.9ce-2.amzn2.x86_64.rpm | 30 MB 00:00:00
-----------------------------------------------------------------------------------------------------------------------------------
Total 75 MB/s | 51 MB 00:00:00

...


[ =1.8.0_192 =1.8.0_202 =1.8.0_212 =1.8.0_222 =1.8.0_232
=1.8.0_242 ]
28 firecracker available [ =0.11 ]
29 golang1.11 available \
[ =1.11.3 =1.11.11 =1.11.13 ]
30 squid4 available [ =4 ]
31 php7.3 available \
[ =7.3.2 =7.3.3 =7.3.4 =7.3.6 =7.3.8 =7.3.9 =7.3.10
=7.3.11 =7.3.13 ]
32 lustre2.10 available [ =2.10.5 =2.10.8 ]
33 java-openjdk11 available [ =11 ]
34 lynis available [ =stable ]
35 kernel-ng available [ =stable ]
36 BCC available [ =0.x ]
37 mono available [ =5.x ]
38 nginx1 available [ =stable ]
39 ruby2.6 available [ =2.6 ]
40 mock available [ =stable ]
41 postgresql11 available [ =11 ]
[ec2-user@ip-172-20-1-221 ~]$

# 버전확인
[ec2-user@ip-172-20-1-221 ~]$ docker --version
Docker version 18.09.9-ce, build 039a7df
[ec2-user@ip-172-20-1-221 ~]$
 

3. 설치를 했으니 돌려봅시다.

$ sudo systemctl start docker
[ec2-user@ip-172-20-1-221 ~]$ sudo systemctl start docker

[ec2-user@ip-172-20-1-221 ~]$ ps -ef | grep docker
root 22846 1 1 08:23 ? 00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit nofile=1024:4096
ec2-user 23025 4157 0 08:23 pts/0 00:00:00 grep --color=auto docker
 

4. ec2-user에게 권한을..

$ sudo usermod -aG docker ec2-user
[ec2-user@ip-172-20-1-221 ~]$ sudo systemctl start docker

[ec2-user@ip-172-20-1-221 ~]$ ps -ef | grep docker
root 22846 1 1 08:23 ? 00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit nofile=1024:4096
ec2-user 23025 4157 0 08:23 pts/0 00:00:00 grep --color=auto docker

# 적용을 위하여 다시 ssh 재접속을 합니다
# exit로 나간뒤 접속 ㄱㄱ
# sudo 명령어 없이 실행해봅니다.

[ec2-user@ip-172-20-1-221 ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[ec2-user@ip-172-20-1-221 ~]$

 

 
+ 번외로 docker는 Server-Client 구조입니다.
# docker verision으로 각각의 버전확인 가능
[kbseo@ip-172-20-1-221 ~]$ docker version
Client:
Version: 18.09.9-ce
API version: 1.39
Go version: go1.10.3
Git commit: 039a7df
Built: Fri Nov 1 19:26:49 2019
OS/Arch: linux/amd64
Experimental: false

Server:
Engine:
Version: 18.09.9-ce
API version: 1.39 (minimum version 1.12)
Go version: go1.10.3
Git commit: 039a7df
Built: Fri Nov 1 19:28:24 2019
OS/Arch: linux/amd64
Experimental: false
 
설치를 완료하였으니
본격적으로 도커 사용법에 대해 알아보도록 하겠습니다!
다음 글에서 계속할께요....
 

Container / Docker

컨테이너.. 들어봤는데 무엇인지 잘 모르겠다..라고 생각하시는 분들을 위하여 이 글을 연재합니다.
 
 

1. Container

보통 IT인이 아니라고 한다면 '컨테이너' 라는 말을 듣는다면 다음의 그림을 상상하실 겁니다.
 
 
사전적 의미로 컨테이너는 어떤 물체를 격리하는 공간을 뜻합니다. 하지만 저희 에게 컨테이너는 어떤 의미 일까요?
컨테이너는 리눅스 기술을 사용하여 선박의 컨테이너 처럼 프로세스가 사용하는 자원을 격리 하는 것입니다
 
 
 
 
가상 환경에 익숙하다면 컨테이너를 가상 머신(VM)에 비교하여 생각하면 이해하기 쉽습니다.
컨테이너는 가상머신과 마찬가지로 애플리케이션을 관련 라이브러리 및 종속 항목과 함께 패키지로 묶어 소프트웨어 서비스 구동을 위한 격리 환경을 마련해 줍니다.
그러나 위의 그림에서 살펴보듯 VM과의 유사점은 여기까지 입니다.
컨테이너를 사용하면 개발자와 IT 운영팀이 훨씬 작은 단위로 업무를 수행할 수 있으므로 그에 따른 이점도 훨씬 많습니다.

장점

  • 가벼움
  • 탄력성
  • 유지 관리 효율
각각의 장점들에 대해서 한가지씩 보도록 하겠습니다.
 
- 가벼움
사용자의 Request Traffic 이 증가함에 따라, 가상머신이나 컨테이너를 추가적으로 배포합니다.
하지만 가상머신의 크기는 최소 몇 GB이지만, 컨테이너의 경우 Guest OS가 없기에 MB단위의 크기를 가집니다.
결과적으로 가상머신은 배포하는데 수분에서 수 십분의 시간이 소요되지만, 컨테이너는 배포에 소요되는 몇 초 밖에 걸리지 않습니다.
 
- 탄력성
 
컨테이너는 Linux, Windows운영체제, 가상머신, 베어메탈, Local pc, Data Center, Public Cloud등 어느 환경 에서나 구동 되므로 개발 및 배포가 크게 쉬워집니다.
 
- 유지관리 효율
 
운영 체제 커널이 하나밖에 없기 때문에 운영 체제 수준에서 업데이트 또는 패치 작업을 한 번만 수행하면 변경 사항이 모든 컨테이너에 적용됩니다.
이를 통해 서버를 더 효율적으로 운영하고 유지 관리할 수 있습니다.

2. Docker

보통 컨테이너 = 도커 라고 생각하실 분들이 많은데 
컨테이너 > 도커 라고 생각하시면 이해가 쉬우실 것 같습니다.
도커에 대해 알아보기 전에 도커의 아키텍처에 대해 먼저 설명드리겠습니다.
 
 
 
 
다음과 같은 형태로 도커가 실행이 되는데 이를 좀더 들여다 보면 아래와 같습니다. 
 
 
 
 
2018년도 DockerCon에서 나온 도커 아키텍처를 보면, 위와 같습니다.
도커안에는 여러 컴포넌트들이 있지만 크게 3가지로 나누어 보겠습니다.
  • docker engine 여러분 모두가 아는 그 엔진, 이 엔진
  • containerd 표준 container 런타임으로 Docker로 부터 분리된 고급 런타임
  • runc Open Container Initiative (OCI) 규격에 맞게 컨테이너를 실행하고 생성하는 CLI 도구
OCI (Open Container Initiative)는? 컨테이너 포맷과 런타임에 대한 개방형 업계 표준을 만들기 위한 목적으로  Linux Foundation 의 지원으로 구성된 오픈 거버넌스 조직 (프로젝트)입니다. OCI는 2015년 6월 22일에 Docker 사와  CoreOS 사가 각각 별도로 표준화를 진행하고 있던 컨테이너의 규격을 통일하는 것을 목적으로  Docker, CoreOS 그리고  AWS, Google, Microsoft, IBM 등 주요 플랫폼 벤더가 참여하여 2015 년 6 월에 발족 한 단체이다. 즉, OCI 는 컨테이너 규격을 통일하는 것을 목적으로 만들어진 조직
 
이러한 도커는 아래와 같은 형태로 작동을 하는데요
 
 
간략하게 설명드리자면
  1. 코드개발
  2. Dockerfile 생성
  3. Dockerfile Image 생성
  4. Container Orchestrator를 통한 배포
  5. Container run
  6. Container image Push
의 순서로 작동을 하게 됩니다.
여기에서 중요한 점은 코드를 이미지화 하며 배포한다는 점입니다.
잠깐! Oh wait!! 이미지화를 하면 어떤점이 좋을까요?
예를 들어 신규 애플리케이션을 만든다고 가정했을 시 일단 인프라 환경을 먼저 구축할것입니다.
 
   
 
서버도 만들어야하고 데이터를 저장할 데이터베이스도 만들어야겠죠...
할일이 벌써 많은 기분이네요...
요즘 그래도 CLOUD 환경이 많기에 클릭클릭클릭 만 해주면 예전에 비해 구축법이 많이 간편해 졌습니다!!
(클라우드 짱짱!)
하.지.만! 서버환경이 조금 씩 다른 서버 수십대를 생성하려면....?
 
 
 
이 또한 매우 반복되는 작업일 것입니다..
이렇게 반복되는 과정속에 '필요한것은 미리 만들어 놓자!' 라는 아이디어가 나오게 되고
서서히 이미지화를 하게 됩니다.
 
 
AWS에서는 AMI(Amazon Machine Image)형태로 이미지를 관리하고
Docker에서는 Docker Image 형태로 이미지를 관리합니다,
 
 
 
→ 보통 생성된 이미지를 통해 OS를 실행하게 되고,
 
 
 
 
→ 실행된 OS에서 이것저것 요청에 따라 설정사항들을 변경하고, 이를 토대로 다시 이미지를 재 생성하게 됩니다.
하. 지. 만.
시간이 서서히 지나면서 이미지가 쌓이게 되면서
 


뭐가 변경된 건지 알수가 없습니다..... ( 저만 그런가요ㅜㅜ? )
 
 
 
그래서
 
 
 
 
이미 다양한 코드화를 위한 도구들이 존재합니다.
 
 
 
오늘의 주인공 도커는 도커 파일 로 코드들을 관리하고 있습니다.
 
 
 
위와같은 전반적인 흐름으로 도커가 실행되고 있습니다.
여기에서! 도커이미지를 Docker Hub같은 Registry에 업로드 할때 PUSH라는 명령어를 쓰고  각 서버에서 이미지를 다운받을 때 이미지를 떙겨온다 해서 PULL이라는 명령어를 씁니다! 명령어는 다음시간에 자세히 다뤄보겠습니다~ (홍보주의)
지금까지 컨테이너와 도커의 기본적인 개념아닌 개념에 대하여 살펴보았는데
그렇담 
아니, 나는 컨테이너는 쿠버네티스 인줄알았는데?
아니 도커는 뭐고 쿠버네티스는 뭐지?
쿠버네티스 어디서 들어본거같은데?
라고 생각하시는 분들을 위하여 Container Orchestration에 대해 자세히 알아보는 시간을 가지겠습니다 (오늘은...시간이 늦어서....)
 
 
 
 

AWS 서비스를 사용하기 위해서는  계정부터 만들어야 겠지요?

이 페이지에서는 AWS 계정을 만드는 법을 설명해 드리도록 하겠습니다.

 


 

 

1. 계정만들기

01 ) 먼저, 아마존 웹 서비스(이하 AWS) 사이트에 접속합니다 

http://aws.amazon.com/

콘솔 로그인창으로 바로 접속하셔도 무방합니다.

http://console.aws.amazon.com

 

콘솔창으로 바로 들어오신분은 [AWS계정 새로만들기]를 클릭합니다



0 2 ) AWS 계정 생성 페이지로 들어옵니다.

필요한 빈칸을 모두 입력하여 줍니다.

이메일주소, 암호, 사용자가 지정하는 계정이름을 적고 하단의 주황색 버튼을 누릅니다.

 

0 3 ) 연락처 정보를 기입합니다.

우편번호는 나중에 비밀번호를 찾을때 사용될 수 있으니 따로 메모해두기를 권장해 드립니다.

추가적으로 해당사항은 영문으로 기입하여 주시길 바랍니다.

 

 

0 4 ) 결제정보를 입력합니다.

 

AWS 가입을 하는데 유료이진 않지만 서비스들을 사용한 만큼 지불하는 방식이기에

미리 결제할 카드를 지정해야 가입이 됩니다.

AWS같은경우 1년간 Free-tier로 정해진 규격내에서 무료로 이용가능하니때문에 

Free-tier로 지원가능한 서비스를 확인하시고 사용하시기를 권장해드립니다. (추가적인 비용이 나가는것을 방지하기 위해)

 

 

AWS Free-tier란? : https://aws.amazon.com/ko/free/faqs/?ft=nf

Free-tier 지원영역 확인하기 : https://aws.amazon.com/ko/free/

 

 

0 5 )  전화번호 인증을 거칩니다.

 

0 6 ) 지원플랜을 선택합니다.

 

 

사용자의 요구에 맞는 플랜을 선택합니다.

우선을 기본플랜으로 가입을 해보도록 하겠습니다.

 

0 7 ) 완료창 확인

가입이 잘 되었나 확인을 하기 위해 콘솔창으로 로그인을 해봅니다.

가입하였던 이메일과 암호를 입력하여 줍니다.

 

 

처음 가입하였을 시 루트 사용자가 되기때문에 상단에 루트사용자 로그인인지 확인하고 접속을 해줍니다.

 

 

입 시 내가 지정해준 이름으로 잘 로그인이 된걸 확인하실수 있습니다.

친절히 AWS측에서 가입축하 메일도 보내줍니다^0^

 

+ Recent posts