๐Ÿ‹ ์ฆ๋ถ„(+ ๋ณ‘๋ ฌ) ์ƒ์„ฑ + ๋ชฉ๋ก =โค๏ธ

10897 ๋‹จ์–ด skopeodockerqemunode
a cross post ์ค‘์— my (not really) blog posts from github์ž…๋‹ˆ๋‹ค.

buildx๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ๊ฐ qemu๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๊ตญ ๊ตฌ์กฐ์— docker ์ด๋ฏธ์ง€๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ด๋ฅผ ๋‹ค์ค‘ ์•„์น˜ ์ด๋ฏธ์ง€๋กœ docker hub์— ๋ฐœํ‘œํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์ž์— ํฌํ•จ๋œ ๋‹จ๊ณ„:
  • ์€ ๊ฐ ์•„ํ‚คํ…์ฒ˜์— ์ด๋ฏธ์ง€๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ์ž„์‹œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ
  • ์œผ๋กœ ์ „์†ก
  • ์ž„์‹œ ๋“ฑ๋กํ‘œ
  • ์— ๋ชฉ๋ก ๋ชฉ๋ก์„ ์ž‘์„ฑํ•˜์—ฌ ์กฐํ•ฉํ•ฉ๋‹ˆ๋‹ค
  • scopeo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„์‹œ ๋“ฑ๋กํ‘œ์—์„œ ๊ณต๊ณต ๋“ฑ๋กํ‘œ๋กœ ๋ณต์‚ฌ
  • ์ด ์ ˆ์ฐจ๋“ค์€ ๋งํ•˜๊ธฐ๋Š” ์‰ฌ์›Œ๋„ ์‹คํ–‰ํ•˜๊ธฐ๋Š” ์–ด๋ ค์›Œ์„œ, ๊ฑฐ์˜ ๋จผ์ € ๋ฌด์—‡์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

    ์˜ˆ์ œ ํ•ญ๋ชฉ
    docker์—์„œ ์‹คํ–‰๋˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค.๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.
    ํ”Œ๋žซํผ.
  • linux/amd64
  • linux/arm64/v8
  • linux/arm/v7
  • linux/arm/v6
  • linux/ppc64le
  • linux/s390x
  • ๋ชจ๋“  ํ”Œ๋žซํผ์— ๋Œ€ํ•ด ๊ตฌ์ถ•์€ ๋ณ‘ํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ'๋‹ค๊ณต๋ฌธ'์ด๋ฏธ์ง€๋งŒ ๋ฐœํ‘œํ•œ๋‹ค.
    ๋ช…์„ธ์„œ).
    ๋‹ค์Œ์€ ์˜ˆ์‹œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค
    // app.js
    const http = require('http');
    
    const port = 3000;
    
    const server = http.createServer((req, res) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Hello World');
    });
    
    server.listen(port, () => {
        console.log(`Server running at %j`, server.address());
    });
    
    ์ด๊ฒƒ์€ Dockerfile์— ๋Œ€ํ•œ ๋ณด์ถฉ์ž…๋‹ˆ๋‹ค. (์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)
    FROM node:14-alpine
    RUN apk add --no-cache tini
    ENTRYPOINT ["/sbin/tini", "--"]
    WORKDIR /app
    COPY ./app.js ./app.js
    CMD [ "node", "/app/app.js" ]
    EXPOSE 3000
    

    ๋‹จ๊ณ„ 1.1: ์„ค์ •
    ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    ๋“ฑ๋กํ‘œ
  • qemu-
  • ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ CPU ์—๋ฎฌ๋ ˆ์ด์…˜
  • binfmt
  • buildx builder, ์œ„ ๋ชจ๋“  ์ฝ˜ํ…์ธ ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Œ

  • ๋‹จ๊ณ„ 1.1.1: ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ
    ์šฐ์„  v2 ๋“ฑ๋กํ‘œ๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ localhost:5000์œผ๋กœ ๊ณต๊ฐœํ•ฉ๋‹ˆ๋‹ค.
    docker run --rm --name registry -p 5000:5000 registry:2
    

    ๋‹จ๊ณ„ 1.1.2:qemu,binfmt,buildx
    ํ˜„์žฌ qemu, binfmt ๊ตฌ์„ฑ์„ ์„ค์ •ํ•˜์—ฌ qemu์„ ์‚ฌ์šฉํ•˜๊ณ  ํŠน์ˆ˜ํ•œ buildx ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ํ˜ธ์ŠคํŠธ ๋„คํŠธ์›Œํฌ.
    sudo apt-get install qemu-user-static
    
    docker run --privileged --rm tonistiigi/binfmt --install all
    
    docker buildx create \
                    --name builder \
                    --driver docker-container \
                    --driver-opt network=host \
                    --use
    
    docker buildx inspect builder --bootstrap
    
    tonistiigi/binfmt --install all์€ docker ์šฉ๊ธฐ๋กœ์„œ "๋ถ€์ž‘์šฉ์ด ์žˆ์Œ"์œผ๋กœ binfmt์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    ํ˜ธ์ŠคํŠธ์˜ ๊ตฌ์„ฑ--driver-opt network=host ํ˜ธ์ŠคํŠธ์—์„œ ์‹คํ–‰ ์ค‘์ธ buildx ์ปจํ…Œ์ด๋„ˆ๋ฅผ registry ํ˜ธ์ŠคํŠธ์— ์—ฐ๊ฒฐlocalhost:5000.buildx inspect --bootstrap์€contianer๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ ์ •๋ณด๋ฅผ ์ธ์‡„ํ•ฉ๋‹ˆ๋‹ค.

    ๋‹จ๊ณ„ 1.2: ๊ตฌ์ถ•
    ์ฐธ๊ณ : ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ํ”Œ๋žซํผ ๋ชฉ๋ก์„ ์ œ๊ณตํ•˜๋ฉด Buildx ์ž์ฒด๊ฐ€ ๊ตฌ์ถ•์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹คbuildx build ๋ช…๋ น์„ --platform ํ‘œ์ง€๋กœ ํ•œ๋‹ค.
    ๋‚ด ์งˆ๋ฌธ๊ณผ ์ด ๊ธ€์„ ์“ด ๋ชจ๋“  ์ด์œ ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ --platforms์„ ํฌํ•จํ•œ๋‹ค๋ฉด
    ๋งŒ์•ฝ ํ”Œ๋žซํผ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํŒจํ•œ๋‹ค๋ฉด, ์ „์ฒด ๊ตฌ์ถ•์€ ์‹คํŒจ๋กœ ํ‘œ์‹œ๋˜๊ณ , ์•„๋ฌด๊ฒƒ๋„ ์–ป์ง€ ๋ชปํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
    ๋˜ ๋‹ค๋ฅธ ์šฉ๋ก€๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์•„์น˜ํ˜• ๋ฌธ ์ด๋ฏธ์ง€์™€ ํ•จ๊ป˜ ์•„์น˜ํ˜• ๋ฌธ์— ํŠน์ •ํ•œ ์ €์žฅ์†Œ๋ฅผ ์ „์†กํ•˜๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    ์˜ˆ: docker.io/app/app, docker.io/arm64v8/app ๋ฐ docker.io/amd64/app)
    ๋˜ ๋‹ค๋ฅธ ์ƒํ™ฉ์€ ๋‚ด๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€์˜ ์‹ค์ œ ๊ธฐ๊ณ„์— ๊ตฌ์ถ•ํ•œ ๊ฒƒ์ด๋‹ค. ์ด ๊ธฐ๊ณ„๋“ค์€ ๋ณธ ๊ธฐ๊ณ„๊ฐ€ arm/v6, arm/v7๊ณผ arm64/v8์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
    CPU (์„œ๋กœ ๋‹ค๋ฅธ PI์™€ ์œ ์‚ฌํ•œ CPU๋กœ ๊ตฌ์„ฑ๋œ ์ง‘๋‹จ).
    ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ตฌ์ถ•ํ•˜๊ณ  ์‹ถ์€ ์ด์œ ๊ฐ€ ๋” ๋งŽ์„ ๊ฑฐ์˜ˆ์š”.๐Ÿคท.
    ํ˜„์žฌ ์šฐ๋ฆฌ๋Š” ๋ณธ ์˜ˆ์˜ buildx ๊ตฌ์ถ•๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋กœ ๋‹ค๋ฅธ ์ฒด๊ณ„ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ถ•ํ•  ์ค€๋น„๊ฐ€ ๋˜์–ด ์žˆ๋‹ค.
    base alpine ์ด๋ฏธ์ง€๋Š” ๋‹ค์Œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • linux/amd64
  • linux/arm/v6
  • linux/arm/v7
  • linux/arm64/v8
  • linux/ppc64le
  • linux/s390x
  • ๋ชจ๋‘๋ฅผ ๊ฒจ๋ˆ„๋ž˜์š”.๐Ÿ˜Ž
    docker buildx build \
            --tag localhost:5000/app:linux-amd64 \
            --platform linux/amd64 \
            --load \
            --progress plain \
            . > /dev/null 2>&1 &
    docker buildx build \
            --tag localhost:5000/app:linux-arm-v6 \
            --platform linux/arm/v6 \
            --load \
            --progress plain \
            .> /dev/null 2>&1 &
    docker buildx build \
            --tag localhost:5000/app:linux-arm-v7 \
            --platform linux/arm/v7 \
            --load \
            --progress plain \
            .> /dev/null 2>&1 &
    docker buildx build \
            --tag localhost:5000/app:linux-arm64-v8 \
            --platform linux/arm64/v8 \
            --load \
            --progress plain \
            .> /dev/null 2>&1 &
    docker buildx build \
            --tag localhost:5000/app:linux-ppc64le \
            --platform linux/ppc64le \
            --load \
            --progress plain \
            .> /dev/null 2>&1 &
    docker buildx build \
            --tag localhost:5000/app:linux-s390x \
            --platform linux/s390x \
            --load \
            --progress plain \
            .> /dev/null 2>&1 &
    wait
    
    
    ์™„๋ฃŒ๋˜๋ฉด docker images ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•˜๊ณ  ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
    $ docker images
    
    ...
    localhost:5000/app   linux-arm64-v8    e3ec56e457e6   About a minute ago   115MB
    localhost:5000/app   linux-arm-v7      ab770e5be5d1   About a minute ago   106MB
    localhost:5000/app   linux-ppc64le     3a328d516acf   About a minute ago   126MB
    localhost:5000/app   linux-s390x       73e064c0c3d4   About a minute ago   119MB
    localhost:5000/app   linux-amd64       f6260fedf498   About a minute ago   116MB
    localhost:5000/app   linux-arm-v6      5a1fb75b0a45   2 minutes ago        110MB
    ...
    
    --load ์ด๋ฏธ์ง€๋ฅผ ๋กœ์ปฌ docker์— ๋ณด๋‚ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. buildx์„ ๋กœ์ปฌ ๋“ฑ๋กํ‘œ๋กœ ์ง์ ‘ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ด ์˜ˆ์—์„œ, ์ด ๊ทธ๋ฆผ๋“ค์„ ์ถ”๊ฐ€ ์ ˆ์ฐจ๋กœ ๋ฐ€์–ด๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
    docker push --all-tags -q localhost:5000/app
    

    2๋‹จ๊ณ„: ์ฒดํฌ๋ฆฌ์ŠคํŠธ
    ์ด์ œ ์šฐ๋ฆฌ๋Š” ์ด ๊ทธ๋ฆผ๋“ค์„ ํฐ ๋ชฉ๋ก์— ์กฐํ•ฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
    docker manifest create --insecure
        localhost:5000/app:1.0.0 \
            localhost:5000/app:linux-amd64 \
            localhost:5000/app:linux-arm-v6 \
            localhost:5000/app:linux-arm-v7 \
            localhost:5000/app:linux-arm64-v8 \
            localhost:5000/app:linux-ppc64le \
            localhost:5000/app:linux-s390x
    
    docker manifest push localhost:5000/app:1.0.0
    

    STEP 3.1: Skopeo
    ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๋Š” ๋ชฉ๋ก ๋ชฉ๋ก์„ ๋ณต์‚ฌํ•˜๊ณ  ๋งํฌ๋œblob๋งŒ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.์ด๋ฅผ ์œ„ํ•ด skopeo์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    ์ด๊ฒƒ์€ ์•„์ฃผ ์ข‹์€ ๋“ฑ๋ก ๋„๊ตฌ๋‹ค.
    ํผ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฑฐ๋‚˜, ubuntu 20.04์— ๋Œ€ํ•ด์„œ๋Š” ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ kubic ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ฐธ๊ณ : ์ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ์„ค์น˜ ์ง€์นจ์„ ๋”ฐ๋ฅด๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    https://github.com/containers/skopeo/blob/master/install.md
    OS="x$(lsb_release --id -s)_$(lsb_release --release -s)"
    echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/${OS}/ /" > /etc/apt/sources.list.d/skopeop.kubic.list
    wget -qO- "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/${OS}/Release.key" | apt-key add -
    apt-get update
    apt-get install -y skopeo
    
    ํ˜„์žฌ, ์šฐ๋ฆฌ์˜ ๋กœ์ปฌ ๋“ฑ๋กํ‘œ๊ฐ€ ์•ˆ์ „ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๊ฐ€ ๋ณต์ œ๋ฅผ ์‹œ๋„ํ•  ๋•Œ, skopeo์€ ๋ถˆํ‰์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๋Š” ๋ช…ํ™•ํ•˜๊ฒŒ
    ์ž„์‹œ ๋“ฑ๋กํ‘œ์— ์•ˆ์ „ํ•˜์ง€ ์•Š๊ฒŒ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    [[registry]]
    location = 'localhost:5000'
    insecure = true
    
    ์ด ํŒŒ์ผ์„ /etc/containers/registries.conf.d/localhost-5000.conf์— ์ƒ์„ฑ

    ๋‹จ๊ณ„ 3.2: ๋ณต์ œ
    ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๋Š” localhost:5000/app:1.0.0์„ hertzg/example:app-1.0.0์œผ๋กœ๋งŒ ๋ณต์ œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
    ์šฐ์„ , ๊ท€ํ•˜๋Š” ๋ชฉํ‘œ ๋“ฑ๋กํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ ๋ถ„ ๊ฒ€์ฆ์„ ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค
    skopeo login docker.io
    
    ์ด์ œ ์ €ํฌ๊ฐ€ ๋“œ๋””์–ด ๊ทธ๋ฆผ์„ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋์–ด์š”.
    skopeo copy \
            --all \
            docker://localhost:5000/app:1.0.0 \
            docker://docker.io/hertzg/example:app-1.0.0
    
    ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ฆด ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์™„์„ฑ๋˜๋ฉด docker hub์„ ๊ฒ€์‚ฌํ•˜๊ฑฐ๋‚˜, ๋Œ€์ƒ์—์„œ ๊ทธ๋ฆผ์„ ๋“œ๋ž˜๊ทธํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
    ๊ฑด์ถ•ํ•˜๋‹ค
    docker run --rm -it hertzg/example:app-1.0.0
    
    ์ด๋ ‡๊ฒŒ

    ๋„๊ตฌ์ฑ…
    ํ‘œ์ง€ ์‚ฌ์ง„

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ