
Docker
설치
Docker
를 이용한 배포하기
하나의 이미지를 다루는 방식과 두개 이상의 이미지를 다루는 방식으로 나눠서 알아보자
먼저 Docker
설치가 필요
ubuntu를 사용하는 경우 아래 링크를 참고해 설치하자
https://docs.docker.com/engine/install/ubuntu/
Install Docker Engine on Ubuntu
docs.docker.com
Docker Engine 설치가 끝나면, Docker Compose
설치도 진행해야 한다
https://docs.docker.com/compose/install/
Install Docker Compose
docs.docker.com
위 설치가 다 정상적으로 되었다면, docker-compose --version
, docker --version
을 해서 오류없이 버전이 정상 출력되면 정상 설치된 것이다
주의: ubuntu 운영체제로 진행할 때는 모든 명령어 앞에 기본적으로 sudo를 붙인다고 생각하면 된다
학습 목표
* 컨테이너 기술과 도커의 필요성
* 컨테이너와 이미지, 레지스트리
* 대표적인 레지스트리인 Docker Hub를 통한 이미지 검색, 사용
* 한 개의 이미지를 이용한 컨테이너 구축
* 두 개 이상의 이미지를 이용한 컨테이너 구축(어떻게 연결되는지 확인)
* Docker CLI에서 명령어를 사용한 이미지 생성/수정/배포, 컨테이너 생성/삭제
Docker
를 사용하는 이유
컨테이너 기술과 Docker의 탄생 배경
- 컨테이너
- 우리가 일반적으로 생각하는 컨테이너
- 항구에서 물류 운반 시에 그 컨테이너
- 컨테이너가 생기면서 물류에는 혁신이 일어남
- 물자를 싣고 내릴 때, 선박의 계류 시간을 획기적으로 단축
- 물자를 싣고 내릴 때, 필요한 인력을 대폭 감소
- 우리가 일반적으로 생각하는 컨테이너
이러한 컨테이너 기술을 소프트웨어 수송; 배포에 적용한게 리눅스 컨테이너(lxc)
애플리케이션을 쉽게 컨테이너화할 수 있게 해주는 생태계 혹은 커뮤니티인, Docker
에서 제공하는 Docker Hub
라는 소프트웨어 저장소가 등장하면서 개발자들이 쉽게 애플리케이션을 포장하고 컨테이너 방식으로 실행할 수 있게 됨
- 컨테이너 방식으로 애플리케이션을 실행하는 것의 장점
- 실행 환경에 구애받지 않고 애플리케이션을 실행할 수 있다
컨테이너 방식의 장점
의존성 충돌 문제를 해결
기본적으로 특정 애플리케이션을 실행하기 위해서는 반드시 어떤 환경(제반 환경)이 구축되어 있어야 한다
→ ex) 윈도우용 프로그램 설치시 .NET Framework
를 설치해라는 문구
이처럼 어떤 프로그램(A) 실행에 다른 프로그램(B)가 반드시 필요한 경우
→ 프로그램 A는 프로그램 B에 의존 관계를 가지고 있다 라고 함
그런데, 하나의 프로그램에 의존적인 여러 프로그램들 그 각각이 서로 다른 버전에 대해서 의존적이라면, 의존성 충돌의 문제가 발생할 수 있다
// 의존성 충돌의 예
wordpress 5.2 → php 7
drupal 8.1 → php 6
둘다 설치하는 경우?
wordpress 5.2 → php ?
drupal 8.1 → php ?
컨테이너 기술을 통해 이러한 의존성 충돌
의 문제를 해결 가능하다
→ 컨테이너 내에 애플리케이션을 구성함
→ 컨테이너에서 실행되는 애플리케이션은 어떠한 의존성도 공유하지 않고, 각자 고유의 의존성을 가지고 있음
→ 컨테이너에서 철저하게 자가 격리
된다고 생각하면 편함(실행 환경이 격리됨)
컨테이너 내에서 격리되고, 독립적으로 소유되는 자원
- 프로세스
- 특정 컨테이너에서 작동하는 프로세스는 기본적으로 그 컨테이너 안에서만 액세스 가능
- 컨테이너 안에서 실행되는 프로세스는 다른 컨테이너의 프로세스에 영향x
- 네트워크
- 기본적으로 컨테이너 1개에 하나의 IP 주소 할당됨
- 파일 시스템
- 컨테이너 안에서 사용되는 파일 시스템은 구획화됨
- 해당 컨테이너에서의 명령이나 파일 액세스 등을 제한 가능
- 컨테이너 안에서 사용되는 파일 시스템은 구획화됨
컨테이너와 가상머신?
리눅스 컨테이너 기술은 엄밀히 말하면 가상 머신의 접근 방법과는 다르다. 단지, 컨테이너가 가상 머신과 비슷한 수준의 격리성을 제공한다는 점 정도만 알면 된다
개발과 배포 환경을 일치
개발시의 환경 구축(개발팀)
- 도커가 없는 개발 환경 구축
- 여러 개발자가 하나의 애플리케이션 개발을 위해, 비슷한 개발 환경을 구축해야 함(특정 버전의 프로그램, 시스템별 맞는 환경 변수 구성 등)
→ 사전 개발 환경을 비슷하게 맞추는 데만도 시간적 소요가 많이 듬(험난한 과정)
- 여러 개발자가 하나의 애플리케이션 개발을 위해, 비슷한 개발 환경을 구축해야 함(특정 버전의 프로그램, 시스템별 맞는 환경 변수 구성 등)
- 도커를 이용한 개발 환경 구축: 개발 환경 일치
- 도커가 실행 중이면, 어떠한 운영체제든 상관없이 동일한 명령어로 어떤 프로그램을 설치, 실행 등 가능
→ OS에 상관없이 즉시 애플리케이션 실행 환경 구축 가능
→ 개발을 컨테이너 위에서 진행할 경우, 모든 개발팀이 동일한 환경에서 개발을 진행 가능
- 도커가 실행 중이면, 어떠한 운영체제든 상관없이 동일한 명령어로 어떤 프로그램을 설치, 실행 등 가능
배포 시의 문제 해결(배포 환경 걱정x)
개발 환경의 일치 이슈는 서비스 배포 환경에도 동일하게 적용할 수 있다
→ 어떤 애플리케이션이 특정 런타임 환경 위에서 실행되고, 사용자에게 이를 제공한다 는 것인데, 이는 앞서 말한 실행 환경 구성과 본질적으로 다를 것이 없기 때문
- 배포 파일 업로드 방식의 개선
- 기존: 서버에 파일 하나하나씩 업로드
- 도커: 컨테이너의 담아서 업로드
이에 따라 서버도 컨테이너의 담긴 애플리케이션을 실행하는 방식으로 서비스를 제공한다
→ ex) AWS의 EC2 상에 Docker
를 설치하거나, AWS ECS 서비스를 이용하면 더욱 쉽게 애플리케이션 배포 가능
손쉬운 수평적 확장 및 새로운 내용 배포
컨테이너 기술의 가장 큰 장점인 실행 환경의 일치 를 생각하면 쉽게 이해 가능하다
서버에 대한 트래픽이 증가하여 서버를 증설할 때, 컨테이너 기술을 활용하면
→ 동일한 애플리케이션 구성(이미지)을 바탕으로 새로운 서버에 해당 애플리케이션을 컨테이너로 실행하고, 로드 밸런서에 이 서버를 추가해 주면 끝(수평적 확장 끝)
- 손쉬운 새로운 내용 배포: 위를 응용한 것. 새로운 버전의 애플리케이션을 여러 서버 중 몇대에만 운영하여 테스트도 가능(문제점 미리 확인용)
오케스트레이션 도구
(ex. 쿠버네티스)가 이러한 일을 해주는 도구
도커의 핵심 키워드 정리
- 컨테이너
- 애플리케이션이 의존성, 네트워크 환경, 파일 시스템에 구애받지 않고, 도커라는 기술 위에 실행될 수 있도록 만든 애플리케이션 상자(박스)
- 이미지: 애플리케이션 및 애플리케이션 구성을 함께 담아 둔 템플릿
- 실행되는 모든 컨테이너는 이미지로부터 생성됨
- 이미지로 여러 개의 컨테이너 생성 가능
- 기본 이미지로부터 변경 사항을 추가/커밋해서 또다른 이미지 생성 가능
- 레지스트리
- 이미지는 레지스트리에 저장됨
- 대표적인 이미지 레지스트리: Docker Hub, Amazon ECR
- 도커 CLI에서 이미지를 통해 컨테이너 생성 시, 호스트 컴퓨터에 이미지가 존재하지 않으면 기본 레지스트리로부터 다운로드받음
Docker CLI
Docker 이미지와 컨테이너를 다루기 위한 Docker CLI
명령어들
주의: ubuntu에서 Docker CLI 명령어를 사용시에는 관리자 권한(sudo)로 실행해야 한다
그렇지 않으면 permission denied 뜬다
Docker 공식 문서에서 사용법 및 명령어, 옵션 등을 확인할 수 있음
https://docs.docker.com/engine/reference/commandline/container_run/
docker container run
docker container run: Run a command in a new container
docs.docker.com
- 사용법: Docker CLI, Docker-Compose, API Reference 참고
- 환경 및 빌드 파일 구성: DockerFile, Docker-Compose File 참고
Docker CLI 연습 1: 기초 명령어
![]() |
연습1: docker/whalesay
docker/whalesay
이미지로 연습해 보자
docker/whalesay
는 레지스트리 계정, 레포지토리 이름, 태그 총 3가지 정보로 구성되어 있다
- docker/whalesay 의 구성 형태
Registry_Account/Repository_Name:Tag
- 레지스트리
- Docker Hub: https://hub.docker.com/
- 도커 이미지를 관리하는 공간
- 지정하지 않으면 기본값(도커 허브)
- 레포지토리
- 레지스트리 내에 도커 이미지가 저장되는 공간
- 이미지 이름이 사용되기도 함
- GitHub의 레포지토리와 유사한 느낌?
- 태그
- 같은 이미지라도 버전 별로 안의 내용이 다른 경우 존재하니깐
- 해당 이미지를 설명하는 버전 정보를 주로 입력
- 지정하지 않으면 기본값으로 lastest 태그를 붙인 이미지를 가져옴
Docker Hub에서 Docker Image를 찾거나, Docker Image의 사용방법을 확인할 수 있다
사용법 등을 확인했다면, CLI에서 진행
## 우분투면 앞에 sudo 붙이기!
docker image pull docker/whalesay:lastest
## {image} pull 레지스트리에서 이미지 혹은 레포지토리를 가져옴
docker image ls ## 이미지 리스트를 출력
## 받아온 이미지를 실행(이미지 → 컨테이너)
## docker container run [OPTIONS] IMAGE [COMMAND] [ARG…]
docker container run --name 컨테이너_이름 docker/whalesay:latest cowsay boo
## 컨테이너_이름을 이름으로 갖는 컨테이너 실행
## [command]는 초기 컨테이너 실행시 수행되는 명령어
## [arg…]는 command에 넘겨질 파라미터
docker container ps -a ## 모든 컨테이너의 리스트를 출력
## {container} ps: 컨테이너의 리스트 출력
## -a 옵션: default로는 실행되는 컨테이너지만 종료된 컨테이너를 포함한 모든 컨테이너 출력
docker container rm 컨테이너이름
## {container} rm : 컨테이너를 삭제. 컨테이너이름은
## ps 명령을 통한 NAMES나 CONTAINER ID를 사용
## 마찬가지로 이미지도 지울 수 있다
docker image rm 이미지이름
![]() |
이 같은 과정은 한번에도 연속되게 실행 가능하다
docker container run --name 컨테이너이름 --rm docker/whalesay cowsay boo
## 하나의 이미지를 받아와 컨테이너로 실행하고, 컨테이너와 관련된 리소스를 삭제하는 작업
## {container} run: 컨테이너를 실행. 이미지가 없다면 이미지를 받아온 뒤(pull) 실행함
## --rm 옵션: 컨테이너를 `일회성`으로 실행. 컨테이너가 중지되거나 종료될 때, 관련 리소스를 모두 제거
docker image rm docker/whalesay
## 자동 다운로드(pull)되었으므로 다시 삭제
- container는
ctrl+c
로 종료 가능 - 도커의 경우 같은 기능을 수행하는 명령어가 다양하게 존재한다
## rmi 또한 rm과 같은 기능을 수행한다
docker rmi [OPTIONS] IMAGE [IMAGE...]
연습2: danielkraic/asciiquarium
docker run -it --rm danielkraic/asciiquarium:latest
## -it 옵션: -i, -t 를 동시에 사용한 옵션. 사용자와 컨테이너 간 인터렉션이 필요한 경우 사용
## 위에서는 출력되는 화면을 사용자가 지속적으로 보기 위해 사용함
## 가령, Python 명령이 필요하거나 추가로 다른 입력을 받는 경우 이 옵션을 지정하여 사용
Docker CLI 연습 2: copy, dockerfile
다른 사람이 제공한 도커 이미지를 받아 사용하는 경우, 원하는 모든 기능이 구성되어 있지 않을 수 있다
→ 도커 이미지에 파일을 추가하여 도커 이미지를 새로 만드는 방법
→ 로컬에 저장된 파일과 함께 도커 이미지를 이용(로컬 파일과 도커 이미지를 연결)
이 방법은 크게 2가지 방식이 있다
- CP(copy)를 이용하는 방법
- 호스트와 컨테이너 사이에 파일을 복사
- Docker Volume을 이용하는 방법
- 호스트와 컨테이너 사이의 공간을 마운트(mount)
- 마운트?
- 저장 공간을 다른 장치에서 접근할 수 있도록 경로를 허용해서, 마치 하나의 저장 공간을 이용하는 것처럼 보이게 하는 작업
Docker 컨테이너에 파일을 복사(cp)
게임 서버
나 웹 서버
같은 경우 사용할 도구가 도커 이미지에 모두 구성되어 있지 않은 경우가 있음
- 웹서버는 도커 컨테이너로 실행
- 웹 서버를 구성하는 파일은 직접 만들거나 가져온 파일로 구성
- 장점
- 서버에 문제가 생기는 것을 호스트와 별개로 파악 가능
- 문제가 생긴 서버를 끄고, 공장 초기화하듯 도커 이미지로 서버 재구동하면 됨(긴급처방하기 좋음)
해당 레포의 게임 서버 파일(팩맨 게임 서버)을 이용해서 팩맨 게임 서버를 실행해보자
https://github.com/platzhersh/pacman-canvas
GitHub - platzhersh/pacman-canvas: An old classic, re-written in HTML5.
An old classic, re-written in HTML5. Contribute to platzhersh/pacman-canvas development by creating an account on GitHub.
github.com
httpd 웹 서버
먼저 서버를 구동하기 위해 httpd 도커 이미지
를 통해 httpd 웹 서버를 구현
→ httpd(http daemon)은 apache http server를 실행하기 위한 오픈 소스 웹 서버 sw
기본적으로 httpd 는 /usr/local/apache2/htdocs/ 경로에 웹 서버와 관련된 파일들이 저장되어 있다면, 해당 파일을 기반으로 웹 서버가 실행되도록 함
## 레포 클론
git clone git@github.com:codestates/pacman-canvas.git
## git clone git@github.com:platzhersh/pacman-canvas.git
##docker container run
docker container run --name 컨테이너이름 -p 818:80 httpd
## -p 옵션: 로컬 호스트의 포트와 컨테이너의 포트를 연결
## -p [로컬호스트의 포트]:[컨테이너의 포트]
## httpd는 일정 시간 연결 기록이 없으면 서버 가동이 중지됨
## 명령어가 실행되면 터미널을 끄지 말고(켜둔 상태)로 다른 터미널에서 다음 작업을 진행하자
## 컨테이너를 백그라운드에서 실행하려면 -d 옵션을 사용
httpd
가 실행되었다면, 웹 브라우저에서 해당 포트로 접속해보자(localhost:818 또는 127.0.0.1:818)
→ 정상적으로 서버가 열려 있으면, 새로운 터미널에서 작업 진행
## docker container cp 명령어를 통해 로컬 호스트의 파일을 컨테이너에 전달
docker container cp ./ 컨테이너이름:/usr/local/apache2/htdocs/
## 경로를 입력할 때, 상대 경로와 절대 경로를 주의해서 작업할 것!
## docker container cp 명령은 앞 경로의 파일(`./`)을 뒤 경로에 복사하는 명령어
## `./` 으로 한 것은 현재 위치가 pacmac-canvas 디렉토리 안이기 때문임!
다시 웹 브라우저의 해당 경로(httpd)로 접속하면 게임이 구동됨을 알 수 있다
docker exec -it 컨테이너이름 bash 명령어를 통해 컨테이너 내부 터미널로 접속할 수 있다
→ 컨테이너가 뭔가 제대로 안된다거나 컨테이너 내부에 접근해서 뭔가 작업할 때 사용
Docker 이미지 만들기
앞서 만들어본 Docker Container를 이미지 파일로 변환하는 작업
- 이미지로 만들 때의 장점
- 이전에 작업했던 내용을 다시 수행 안해도 된다(반복작업 안해도됨)
→ 배포 및 관리가 유용
- 이전에 작업했던 내용을 다시 수행 안해도 된다(반복작업 안해도됨)
이미지를 만드는 방법에는 크게 2가지가 있다
구동한 Docker Container를 이미지로 만드는 방법
docker container commit
명령을 이용
https://docs.docker.com/engine/reference/commandline/container_commit/
docker container commit
docker container commit: Create a new image from a container's changes
docs.docker.com
docker container commit 컨테이너이름 my_pacman:1.0
## 구동한 컨테이너를 my_pacman 이름의 이미지(레포)로 만듬(1.0은 태그)
## 잘되는지는 생성한 이미지를 구동해보면 된다
docker run --name 이름 -p 900:80 my_pacman:1.0
Docker Image 빌드를 위한 파일인 Dockerfile
로 만드는 방법
해당 공식문서를 참고해서 해보자
https://docs.docker.com/engine/reference/builder/
Dockerfile reference
docs.docker.com
dockerfile을 만들고 dockerfile 대로 이미지를 build 하는 방법
- dockerfile이란?
→이미지 파일의 설명서
같은거
docker build
는 Dockerfile로 도커 이미지 파일을 생성하는 명령어
## --tag 는 name:tag 형식으로 이미지를 생성할 수 있다
## 지정한 경로에 있는 Dockerfile을 찾아서 빌드
docker build --tag my_pacman:2.0 .
##끝에 꼭 "."을 명령어에 꼭 포함해야 한다!
- 생성된 이미지를 이용해 901 포트(원하는 포트)에 웹 서버 구동
docker run --name 원하는이름 -p 901:80 my_pacman:2.0
두개의 docker 이미지를 다루기
docker-compose CLI
두 개 이상의 도커 컨테이너를 연결하는 명령어이다
docker compose 공식 문서를 참고하자
https://docs.docker.com/compose/reference/
Overview of docker-compose CLI
docs.docker.com
docker-compose up ## -d 옵션을 사용하면, 컨테이너를 백그라운드로 실행 가능
## docker-compose.yaml 에 정의된 이미지를 컨테이너로 실행
docker-compose down
## docker-compose.yaml(yml)(에 정의된 이미지를 이용해 실행된) 컨테이너를 종료
docker-compose up {특정이미지}
## 특정 이미지만 컨테이너로 실행
먼저, 위의 명령어들을 사용하려면 docker-compose.yml
(또는 .yaml 확장자명) 파일이 존재해야 한다
docker-compose.yml
- 하나의
docker-compose.yml
에서 관리되는 컨테이너끼리는 동일한 docker network에서 구동된다 docker run
명령과 다르게docker-compose.yml
파일 안에서 기본 network가 사용됨
- 하나의
## 원하는 경로(경로 무관)에서 `docker-compose.yml` 파일을 생성(껍데기)
touch docker-compose.yml ## 껍데기 파일 생성
nano docker-compose.yml ## 코드 작업 진행
## 해당 파일이 있는 위치에서
docker-compose up -d ## 해당 yml 파일을 실행(백그라운드 실행 옵션)
## 이제 브라우저에서 해당 포트로 실행된 화면을 확인하면 된다
아래는 테스트용 예제 소스 코드(복사해서 사용)
version: '3.8'
services:
nginx:
image: sebcontents/client
restart: 'always'
ports:
- "8080:80"
container_name: client
node:
image: sebcontents/server
restart: 'always'
ports:
- "5000:3000"
container_name: server
Volume 과 환경 변수 설정
도커 컨테이너와 데이터 볼륨이라는 개념은 아래 레퍼런스를 참고
https://www.joinc.co.kr/w/man/12/docker/Guide/DataWithContainer
도커 컨테이너 데이터 볼륨 관리
백업, 복구, 마이그레이션
www.joinc.co.kr
volume
을 사용하고, 환경 변수 설정하는 작업을 해보자
테스트용 예제 소스 코드는 아래와 같다
//M1을 제외한 다른 노트북 모델용 yaml(yml) 파일
version: '3.8'
services:
nginx:
image: sebcontents/client
restart: 'always'
ports:
- "8080:80" ## 호스트포트 : 컨테이너포트
container_name: client
node:
image: sebcontents/server
restart: 'always'
ports:
- "5000:3000"
container_name: server
volumes: // volume 을 사용한다는 것
- "./volumefolder:/data"
## 현재 경로의 `/volumefolder` 에 넣는 파일들을 해당 컨테이너의 `/data` 폴더에도
## 넣는다는 뜻(업로드 개념 비슷?)
mysql:
image: mysql:latest
restart: 'always'
ports:
- "3307:3306"
container_name: database
environment:
MYSQL_ROOT_PASSWORD: root_계정_비밀번호 // 사용할 루트 비번
MYSQL_DATABASE: 초기_생성_데이터베이스 // 생성할 초기 db 이름
MYSQL_USER: 유저_이름 // 생성할 유저이름
MYSQL_PASSWORD: 유저_패스워드 // 생성할 유저 비번
마찬가지로 원하는 경로에서 docker-compose.yml
파일을 생성하고 위의 소스 코드를 붙여넣기하자
→ 해당 경로에서 (sudo) docker-compose up -d
로 실행하면, yml 파일이 위치한 곳에 volumefolder
라는 디렉토리가 생성됨을 확인 가능
해당 디렉토리 안에서 임의의 파일 하나를 만들어 보자
→ docker exec -it server bash
명령어를 통해 server
컨테이너 터미널에 접속하여 data 디렉토리로 이동(cd /data)하면 아까 생성한 임의의 파일이 여기에도 존재함을 알 수 있다!
보충 내용
컨테이너 기술과 가상 머신(vm)의 비교
![]() |
컨테이너 vm
==========================================
CPU 성능 공유 다 격리
메모리 공유
네트워크 격리
리눅스커널 공유
파일시스템 격리
프로세스 격리
docker의 장점
- 특히 개발팀 단위로 협업할 때 유용
- 각 개발 환경이 다를 수 있는데, 개발 환경 일치 및 일치 작업에 유리!
- 배포 환경도 일치화할 수 있음
docker 이미지 만들기(유용)
dockerfile
을 이용해서 만들 수 있다
→ 백엔드에서 주로 사용함
아래 node.js 공식문서를 따라해서 일단 껍데기를 만들어보자
https://nodejs.org/ko/docs/guides/nodejs-docker-webapp/
Node.js 웹 앱의 도커라이징 | Node.js
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
nodejs.org
## 어떤 특정 파일들과 코드 작업을 했다고 가정
## back → 기본 앱 서버
## front → fetch API로 설정했다고 가정
## front는 웹 서버 위에서 띄워야 한다
## Dockerfile 을 생성
## 그 후 파일 내용에 코드 작성
## 파일 내용의 소스 코드 예시는 아래와 같다
FROM httpd:2.4 # 베이스 이미지를 httpd:2.4 로 사용합니다.
COPY ./ /usr/local/apache2/htdocs/
## 호스트의 현재 경로에 있는 파일을 생성할 이미지 /usr/local/apache2/htdocs/ 에 복사
## 이 작업이 되면 back(서버쪽)에서도 Dockerfile을 생성해서
## 거기서 서버에 맞는 소스 코드를 작성해야 함
## 소스 코드 작업은 알아서…
## 둘다 소스 코드 작업이 끝났으면 `docker-compose.yml` 파일을 생성해서 그 안에서 작동 코드를 작성
## 작성 코드 예시
version: “3.0”
services:
front:
build: front
ports:
- 80:80
depends_on:
- back
back:
build: back
ports:
-3333:80
## 네트워크가 격리되어있으므로 둘다 80으로 띄워도 문제없다는 점!
## 소스 코드 작업이 끝나면,
docker-compose up ## 하고 웹 브라우저에서 구동됨을 확인
'SE Bootcamp 내용 정리' 카테고리의 다른 글
배포 - AWS 를 이용한 배포 연습(3-Tier Architecture) (0) | 2021.12.09 |
---|---|
배포 - AWS 기초 (0) | 2021.12.09 |
Git - 브랜치(branch) 관리와 그 외 다양한 명령어 (0) | 2021.11.30 |
네트워크 - 심화(프로토콜 계층, HTTP 헤더, 웹 캐시) (0) | 2021.11.30 |
컴퓨터 공학 - 핵심 내용 정리 (0) | 2021.11.26 |