Lab1

μ„Έμ…˜ λͺ©ν‘œ

  • Docker Container build, run, debug

  • Docker Hubλ‘œλΆ€ν„° Docker images pull ν•˜κΈ°

  • Google Container Registry 에 Docker image push ν•˜κΈ°

Google Cloud

Cloud Shell 은 development tools 와 λ‘œλ“œλ˜λŠ” 가상 머신이닀.

gcloud is the command-line tool for Google Cloud. It comes pre-installed on Cloud Shell and supports tab-completion.

Auth list 확인

docker run hello-world

도컀 데λͺ¬μ€ hello-world 이미지λ₯Ό λ‘œμ»¬μ—μ„œ μ°Ύμ§€ λͺ»ν•˜λ©΄ Docker Hubμ—μ„œ 이미지λ₯Ό pullν•˜μ—¬ μ»¨ν…Œμ΄λ„ˆλ₯Ό μƒμ„±ν•˜κ³  μ‹€ν–‰ν•œλ‹€.

이미지λ₯Ό ν’€ ν•œ ν›„ λ‹€μ‹œ ν•΄λ‹Ή λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜λ©΄ 이제 docker daemon은 local registryμ—μ„œ 이미지λ₯Ό μ°Ύκ³ , κ·Έ μ΄λ―Έμ§€λ‘œλΆ€ν„° μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰ν•œλ‹€.

Build

cat > Dockerfile <<EOF
# Use an official Node runtime as the parent image
FROM node:lts
# Set the working directory in the container to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Make the container's port 80 available to the outside world
EXPOSE 80
# Run app.js using node when the container launches
CMD ["node", "app.js"]
EOF
  • The initial line specifies the base parent image, which in this case is the official Docker image for node version long term support (lts).

  • In the second, you set the working (current) directory of the container.

  • In the third, you add the current directory's contents (indicated by the "." ) into the container.

  • Then expose the container's port so it can accept connections on that port and finally run the node command to start the application.

node application

cat > app.js <<EOF
const http = require('http');
const hostname = '0.0.0.0';
const port = 80;
const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\\n');
});
server.listen(port, hostname, () => {
    console.log('Server running at http://%s:%s/', hostname, port);
});
process.on('SIGINT', function() {
    console.log('Caught interrupt signal and will exit');
    process.exit();
});
EOF

μœ„ 파일 μž‘μ„± ν›„ imageλ₯Ό buildν•œλ‹€.

docker build -t node-app:0.1 .
  • -t λͺ…λ Ήμ–΄λŠ” name: tag 둜 νƒœκ·Έλ₯Ό μ§€μ •ν•˜κΈ° μœ„ν•œ λͺ…λ Ήμ–΄.

  • λ”°λΌμ„œ μ΄λ―Έμ§€μ˜ 이름은 node-app 이고, tagλŠ” 0.1이 λœλ‹€.

  • νƒœκ·Έλ₯Ό μ§€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ latest 둜 μ €μž₯λœλ‹€. μ΄λ ‡κ²Œ 되면 μƒˆλ‘œμš΄ 이미지가 생겼을 λ•Œ ν—·κ°ˆλ¦¬κΈ° λ•Œλ¬Έμ— νƒœκ·Έλ₯Ό λ°˜λ“œμ‹œ μ €μž₯ν•˜λŠ” 것이 μ€‘μš”ν•˜λ‹€.

이미지 λΉŒλ“œ ν›„ 도컀 이미지 λͺ©λ‘μ„ ν™•μΈν•œλ‹€.

Run

μœ„μ—μ„œ λΉŒλ“œν•œ 이미지 기반의 μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•œλ‹€.

docker run -p 4000:80 --name my-app node-app:0.1
  • β€”name 은 μ»¨ν…Œμ΄λ„ˆ 이름을 μ§€μ •ν•  수 μžˆλ„λ‘ ν•˜λŠ” λͺ…령어이닀.

  • -p λŠ” 도컀가 호슀트의 포트 4000λ²ˆμ„ μ»¨ν…Œμ΄λ„ˆμ˜ 80번 포트둜 λ§€ν•‘ν•˜λ„λ‘ν•œλ‹€.

  • λ”°λΌμ„œ ν˜ΈμŠ€νŠΈλŠ” http://localhost:4000 μ—μ„œ μ„œλ²„λ₯Ό 확인할 수 μžˆλ‹€.

도컀 μ»¨ν…Œμ΄λ„ˆλ₯Ό λ„μš΄ ν›„ λ‹€λ₯Έ ν„°λ―Έλ„μ—μ„œ μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό 확인해본닀.

curl <http://localhost:4000>

λ‹€μŒκ³Ό 같은 λͺ…λ Ήμ–΄λ₯Ό 확인할 수 μžˆλ‹€.

λ§Œμ•½ μ»¨ν…Œμ΄λ„ˆκ°€ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 데λͺ¬μœΌλ‘œ λŒμ•„κ°€λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œλŠ” -d flagλ₯Ό 뢙인닀.

docker run -p 4000:80 --name my-app -d node-app:0.1
docker ps

도컀 λ‚΄λ Έλ‹€κ°€ backgroundμ—μ„œ run ν•˜λ„λ‘ ν•˜λŠ” λͺ…λ Ήμ–΄

μ»¨ν…Œμ΄λ„ˆ 아이디λ₯Ό 톡해 둜그λ₯Ό ν™•μΈν•œλ‹€.

docker build -t node-app:0.2 .

app.js 파일 λ³€κ²½ ν›„ λ‹€μ‹œ 이미지λ₯Ό λΉŒλ“œν•˜κ³  μƒˆλ‘œμš΄ νƒœκ·Έλ₯Ό 뢙인닀.

step2 μ—μ„œλŠ” 이미 μ‘΄μž¬ν•˜λŠ” cache layerλ₯Ό μ‚¬μš©ν•œλ‹€.

Step3 λΆ€ν„°λŠ” app.jsμ—μ„œ 변경사항이 μžˆμ—ˆκΈ° λ•Œλ¬Έμ— layer듀도 μˆ˜μ •λœλ‹€.

docker run -p 8080:80 --name my-app-2 -d node-app:0.2
docker ps

μƒˆλ‘œμš΄ 이미지λ₯Ό μ΄μš©ν•œ μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰ν•œλ‹€.

이미 호슀트의 4000번 포트λ₯Ό μ‚¬μš©μ€‘μ΄κΈ° λ•Œλ¬Έμ— λ‹€λ₯Έ 포트번호λ₯Ό μ‚¬μš©ν•œλ‹€.

Debug

μ»¨ν…Œμ΄λ„ˆ 아이디λ₯Ό 톡해 도컀 둜그λ₯Ό ν™•μΈν•œλ‹€.

docker logs -f [container_id]
docker exec -it [container_id] bash

μ»¨ν…Œμ΄λ„ˆμ•ˆμ—μ„œ interactive Bash session μ‹€ν–‰

  • -it flagλŠ” pseudo-ttyλ₯Ό ν• λ‹Ήν•¨μœΌλ‘œμ¨ μ»¨ν…Œμ΄λ„ˆμ™€ μƒν˜Έμž‘μš©ν•  수 μžˆλ„λ‘ ν•œλ‹€.

  • bashλŠ” WORKDIR 인 /app μ—μ„œ μ‹€ν–‰λœλ‹€λŠ” 것을 κΈ°μ–΅ν•˜μž. (Dockerfile μ—μ„œ μž‘μ„±ν•¨)

docker inspect [container_id]

Publish

이제 이미지λ₯Ό Google Container Registry (gcr)에 ν‘Έμ‹œν•΄λ³΄μž!

κ·Έ ν›„ μ»¨ν…Œμ΄λ„ˆμ™€ 이미지듀을 μ‚­μ œν•  것이고, κ·Έ λ‹€μŒ ν’€ν•˜κ³  μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‹€ν–‰ν•  것이닀.

gcr에 이미지λ₯Ό ν‘Έμ‹œν•˜κΈ° μœ„ν•΄μ„œλŠ” 이미지 이름을 registry name으둜 νƒœκ·Έν•΄μ•Όν•œλ‹€.

ν˜•μ‹μ€ [hostname]/[project-id]/[image]:[tag] 이닀.

For gcr:

  • [hostname]= gcr.io

  • [project-id]= your project's ID

  • [image]= your image name

  • [tag]= any string tag of your choice. If unspecified, it defaults to "latest".

project IDλŠ” μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•΄ ν™•μΈν•œλ‹€.

gcloud config list project

node-app:0.2 λ₯Ό νƒœκΉ…ν•΄λ³΄μž.

docker tag node-app:0.2 gcr.io/[project-id]/node-app:0.2

이제 이 이미지λ₯Ό gcr에 ν‘Έμ‹œν•΄λ³΄μž.

docker push gcr.io/[project-id]/node-app:0.2

이제 Google Cloudμ—μ„œ 이미지가 잘 ν‘Έμ‹œλ˜μ—ˆλŠ”μ§€ ν™•μΈν•œλ‹€.

이미지 ν…ŒμŠ€νŠΈ

λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ μ‹œλ„ ν•  수 μžˆμ§€λ§Œ κ°„λ‹¨νžˆ μ‘΄μž¬ν•˜λ˜ 기쑴의 μ»¨ν…Œμ΄λ„ˆλ“€μ„ μ‚­μ œν•œλ‹€.

docker stop $(docker ps -q)
docker rm $(docker ps -aq)

node imageλ₯Ό μ§€μš°κΈ° 전에 node:lts 의 child images 듀도 μ‚­μ œν•΄μ•Όν•œλ‹€.

λ‹€μŒ λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•œλ‹€.

docker rmi node-app:0.2 gcr.io/[project-id]/node-app node-app:0.1
docker rmi node:lts
docker rmi $(docker images -aq) # remove remaining images
docker images

이제 이미지λ₯Ό pull ν•˜κ³  μ‹€ν–‰ν•΄λ³΄μž

docker pull gcr.io/[project-id]/node-app:0.2
docker run -p 4000:80 -d gcr.io/[project-id]/node-app:0.2
curl <http://localhost:4000>

Last updated