본문 바로가기
Docker

다양한 Container 생성

by 손영진 2023. 8. 1.
728x90

#1 Container 구조

   1. Container 기술

  • Runc
  • Containerd
    • Container 이미지 다운로드하고 Container 실행 및 감독에 대한 압축을 푸는 Container 수명 주기 관리 Daemon
  • Graph
    • Docker 아키텍처에서 스토리지의 역할과 다운로드 한 Container 미러 이미지 간 관계 기록 재생

   2. Union Filesystem

  • 계층화(Layer)된 파일 시스템 구현
  • 컨테이너에 필수적 기능은 아니지만, 도커에서 이미지 구현에 필요
  • Copy on Write
    • 기존 이미지 위에 추가되는 내용은 Writable Layer에 기록
    • 이미지의 기존 내용 변경 시 해당 Data Writable Layer 에 카피 후 변경

   3. Docker Container 구조

  • Bootfs – Boot filesystem
    • OS에 대한 경계 및 구분으로 어떠한 OS에 들어갈지 정할 수 있다.
  • Image 
    • Read-only Layer로 읽기만 가능한 계층
  • Container
    • writable로 내용에 대한 변경이 가능한 계층
    • Image에서 변경이 불가능한 부분은 Container에서 변경

   4. Container Process

  • Dockerd는 요청을  gRPC 통해 Containerd로 전달
  • Containerd는 exec 을 통해 Containerd-shim 자식으로 생성
  • Containerd-shim은 runc 이용하여 container 생성
  • Runc는 container 정상 실행 시 exit
  • Containerd-shim은 그대로 살아있으며, 이는 container내에서 실행되는 Process들의 부모

   => RuncContainer를 만들어 부모가 되었지만 exit을 통해 container를 나가며 고아로 만들어버린다. 이를 방지하기 위해 Containerd-shim이 살아있어 그 역할을 대신 한다. 이는 부모가 된다는 것을 의미

 

#2 Container 생성 실습

EC2 인스턴스를 통해 생성한 주소에 접속(SSH)한 상태에서 진행

 -> VM을 통해 생성한 네트워크에 접속한 가상네트워크 상태에서 인스턴스에 접속


   1. Container memory 할당 및 생성

docker run --name nginx -d -p 8080:80 --memory="100m" nginx
docker container inspect nginx | grep Memory  // inspect 명령어를 통해 Memory확인

docker container update --memory="200m: nginx

   2. Container CPU 할당 및 생성

docker run --name nginx -d -p 8080:80 --cpuset-cpus=2 nginx  // 몇 번째 CPU 사용 선택
docker container inspect nginx | grep Cpuset

docker run --name nginx2 -d -p 8180:80 --cpus=3 nginx  // CPU 개수 선택
docker inspect nginx2 | grep NanoCpu

   3. Volume 생성 및 확인

docker volume create http-volume // volume을 저장할 수 있도록 저장소를 만든다
docker run --name nginx -d -v http-volume:/usr/share/nginx/html -p 8080:80 nginx
								// -v를 통해 만들어줄 파일이 volume이라는 것을 명시
                                // http-volue:~  의 경로로 저장
docekr ps 						// 생성된 container 확인

docker container exec -it nginx /bin/bash   // 생성한 container에 접속
-> echo 'Docker volume test' > /usr/share/nginx/html/index.html // index.html 파일을 생성과 동시 '' 안의 내용 삽입
-> cat /usr/share/nginx/html/index.html							// 생성한 파일의 내용 확인
-> exit

cat /var/lib/docker/volumes/http-volume/_data/index.html		// container 외에서도 확인

   4. Volume 공유

docker run --name nginx2 -d -v http-volume:/usr/share/nginx/html -p 8180:80 nginx
docker container ls					// 만들어진 2개의 container 확인

curl localhost:8080/index.html
curl localhost:8180/index.html		// 내용이 같음을 확인

   5. Container 삭제 후 Volume 확인

docker container rm -f nginx
docker container rm -f nginx2	// Container 삭제

curl localhost:8080/index.html
curl localhost:8180/index.html	// container 삭제 후 남아있는데 파일 확인
								// volume으로 저장했기에 파일은 남아있음

#3 Docker Image (Pull, Push) / Container 생성

   1. Docker Image 다운로드(Pull)

docker pull centos/httpd-24-centos8		// 패키지로 되어 있는 Image 다운로드
docker images

   2. Container 생성 및 확인

docker run --name httpd -d -p 8180:8080 centos/httpd-24-centos8
							// Image를 통해 httpd의 이름을 가진 container 생성 및 실행
docker container ls 		// 생성된 container 확인

docker container exec -it httpd /bin/bash		// 생성한 container 에 접속
-> echo 'Docker image test' > /var/www/html/index.html
-> exit

curl localhost:8180/index.html

   3. Docker commit : Image 생성

docker container stop httpd
docker container commit -a 'Yeong Jin' -m 'Added index.html file' httpd
							// 지금까지와는 반대로 container를 통해 image 생성

   4. Image 업로드(Push) 및 tag(이름 및 버전 번호 부여, 복사) -> REDHAT 에서 quay.io의 계정 생성

docker image tag 58e16d009c81 private/official-httpd
-> docker image tag [3번에서 생성된 image의 id] [repository에 부여할 이름]

docker image tag private/official-httpd quay.io/syj2927/official-httpd:v1.0
-> docker image tag [repository에 부여한 이름] quay.io/[redhat의 quay.io에서 생성한 아이디 / 복사하여 생성할 이름:tag이름]

docker login quay.io
docker image ls 			// 위에서 생성하고 복사한 image가 제대로 생성되었는지 필히 확인한다

docker image push quay.io/syj2927/official-httpd:v1.0
							// quay.io에 생성한 image를 업로드

   5. Docker save & load

docker save -o official-httpd.tar quay.io/syj2927/official-httpd:v1.0
-> docker save -o [저장되어 기록될 파일 이름] [저장할 파일 이름]

docker rmi -f quay.io/syj2927/official-httpd:v1.0		// image 삭제
docker images			// 남아있는 image를 확인하여 삭제됨을 확인

docker load -i official-httpd.tar				// 저장한 파일 가져오기
docker images			// 삭제했던 image가 재생성된 것을 확인

#4 Dockerfile을 통한 container 생성

   1. Dockerfile 생성

mkdir container
cd container

vim Dockerfile				// 참조 1
vim fix-permissions.sh		// 참조 2
vim docker-entrypoint.sh	// 참조 3

chmod 755 *.sh
docker build -t centos/mariadb .	// 패키징(centos/mariadb)을 받아오며 image 생성 -> ' . ' 필수

docker images

 

참조 1

더보기

FROM centos:centos7

   

MAINTAINER The CentOS Project <cloud-ops@centos.org>

LABEL Vendor="CentOS"

LABEL License=GPLv2

LABEL Version=5.5.41

  

LABEL Build docker build --rm --tag centos/mariadb55 .

  

RUN yum -y install --setopt=tsflags=nodocs epel-release && \

    yum -y install --setopt=tsflags=nodocs mariadb-server bind-utils pwgen psmisc hostname && \

    yum -y erase vim-minimal && \

    yum -y update && yum clean all

  

  

# Fix permissions to allow for running on openshift

COPY fix-permissions.sh ./

RUN ./fix-permissions.sh /var/lib/mysql/   && \

    ./fix-permissions.sh /var/log/mariadb/ && \

    ./fix-permissions.sh /var/run/

  

COPY docker-entrypoint.sh /

  

ENTRYPOINT ["/docker-entrypoint.sh"]

  

# Place VOLUME statement below all changes to /var/lib/mysql

VOLUME /var/lib/mysql  

# By default will run as random user on openshift and the mysql user (27)

# everywhere else

USER 27

  

EXPOSE 3306

CMD ["mysqld_safe"]

 

참조 2

더보기

#!/bin/sh

# Taken from https://raw.githubusercontent.com/openshift/sti-base/servera/bin/fixpermissions

# Fix permissions on the given directory to allow group read/write of

# regular files and execute of directories.

chgrp -R 0 $1

chmod -R g+rw $1

find $1 -type d -exec chmod g+x {} +

 

참조 3

더보기

#!/bin/bash

set -e

if [ "${1:0:1}" = '-' ]; then

           set -- mysqld_safe "$@"

fi   

if [ "$1" = 'mysqld_safe' ]; then

           DATADIR="/var/lib/mysql"

  

          if [ ! -d "$DATADIR/mysql" ]; then

                  if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then                           echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set'                           echo >&2 '  Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?'                           exit 1                   fi

  

                  echo 'Running mysql_install_db ...'                   mysql_install_db --datadir="$DATADIR"                   echo 'Finished mysql_install_db'

  

                  # These statements _must_ be on individual lines, and _must_ end with

                  # semicolons (no line breaks or comments are permitted).

                  # TODO proper SQL escaping on ALL the things D:

  

                  tempSqlFile='/tmp/mysql-first-time.sql'

                  cat > "$tempSqlFile" <<-EOSQL

                         DELETE FROM mysql.user;

                          CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';

                          GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION;

                          DROP DATABASE IF EXISTS test;

                  EOSQL

  

                  if [ "$MYSQL_DATABASE" ]; then

                          echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\`;" >> "$tempSqlFile"                           if [ "$MYSQL_CHARSET" ]; then

                          echo "ALTER DATABASE \`$MYSQL_DATABASE\` CHARACTER SET \`$MYSQL_CHARSET\`;" >>"$tempSqlFile"                           fi

  

                          if [ "$MYSQL_COLLATION" ]; then

                           echo "ALTER DATABASE \`$MYSQL_DATABASE\` COLLATE \`$MYSQL_COLLATION\`;" >> "$tempSqlFile"                           fi                   fi

  

                  if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then                    echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';" >>"$tempSqlFile"

  

                          if [ "$MYSQL_DATABASE" ]; then

                           echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%';" >> "$tempSqlFile"

                         fi

                  fi

  

                  echo 'FLUSH PRIVILEGES;' >> "$tempSqlFile"

  

                  set -- "$@" --init-file="$tempSqlFile"           fi

   fi    exec "$@" 

 참조: github.com/CentOS/CentOS-Dockerfiles/blob/master/mariadb/centos7/docker-entrypoint.sh

 

   2. Container 생성 및 테스트

docker run --name=mariadb -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=r00tpassword centos/mariadb
					// mariadb의 이름을 가진 container 생성
docker container ls

docker exec -it mariadb /bin/bash		// container 접속
-> mysql -uroot -pr00tpassword

mariadb > show databases;
> create database test;
> use test;
> exit

 

#5 Docker GUI 사용법

   1. Potainer 설치

docker volume create portainer_data
docker run --name potainer -d -p 9000:9000 \
> -v /var/run/docker.sock:/var/run/docker.sock:Z \
> -v portainer_data:/data:Z --restart=always portainer/portainer
			// 해당 경로에 따라 9000번 포트번호에 potainer 설치

docker container ls

   2.  Potainer 접근

  • 웹 브라우저에 EC2인스턴스의 공인IP와 포트번호 작성하여 Portainer 열기
    • 공인ip:9000
  • 비밀번호 작성 후 해당 사진들 참고하여 container 생성
  • http-volume 이라는 volume 생성 후 실행
  • 모든 세부사항 작성 후 deploy~ 클릭하여 container 생성

'Docker' 카테고리의 다른 글

Docker 최종 연습  (1) 2023.08.06
Docker Swarm & Monitoring & Podman  (0) 2023.08.06
Docker Network  (0) 2023.08.03
Docker Registry  (0) 2023.08.02
Docker의 기본개념  (1) 2023.07.31