ICTSC2025 一次予選 問題解説: 問16 - 問19

問16

あるプロジェクトで、 Go 言語と Docker Compose を使ったアプリケーションを開発している。以下に、使用しているファイルを挙げる。

以下は app.env である。

PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/bin
USER_NAME=ICTSC

以下は compose.yaml である。

services:
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - ".:/usr"
      - type: bind
        source: ./log
        target: /var/log
    env_file: "app.env"

以下は Dockerfile である。

FROM golang:1.24.5-alpine

COPY main.go run.sh ./
RUN chmod +x run.sh

RUN go build -o app ./main.go

CMD ["./run.sh"]

以下は main.go である。

package main

import (
    "fmt"
    "os"
)

func main() {
 name := os.Getenv("USER_NAME")
 fmt.Println("Hello, " + name)
}

以下は run.sh である。

#!/bin/sh

set -euo pipefail

# マシンの起動時間をログに記録する
uptime > /var/log/app.log

./app | tee -a /var/log/app.log

開発を続けていると、ある日、以下のようなエラーが出てコンテナが起動できなくなってしまった。

./run.sh: line 4: uptime: not found

選択肢の中から、解決のために有効な作業を全て選べ。実施の有無が解決に関与しない選択肢は選んではならない。なお、 Docker Compose のバージョンは 2.23.0 とする。

選択肢(複数選択)

  1. Docker Compose 設定のうちボリューム設定を変更する
  2. 実行時は distroless イメージを使用するようにマルチステージビルドを設定する
  3. イメージの再ビルドとコンテナの再起動を行う
  4. 環境変数の設定を変更する
  5. run.sh の適切な場所に unalias uptime と 追記する
  6. Dockerfile に RUN dnf install <任意のパッケージ> と追記する

解説

Docker コンテナ内で特定のコマンドが実行できないトラブルでした。原因となる設定は二点あります。

  • PATH 環境変数から必要なパスが抜けていること
    • 指定の Docker イメージでは uptime コマンドは /usr/bin にある
    • PATH の値をよく見ると /usr/bin が抜けている
  • /usr ディレクトリがボリューム設定により書き換えられている
    • compose.yaml の7行目で、ホスト側のカレントディレクトリ ./usr にバインドしている

一点目を解決して /usr/binPATH に追加しても、二点目により /usr/bin/uptime はコンテナ内から読み取れません。

したがって解決方法は、

  • Docker Compose 設定のうちボリューム設定を変更する (選択肢 1.)
  • 環境変数の設定を変更する (選択肢 4.)

の二つです。

※選択肢 3. は「イメージの再ビルドを行ったのち、コンテナの再起動を行う(実際には再ビルドは必要ないため不適)」という意図で記述しておりました。しかし設定変更後にはコンテナの再起動が必要になるため、運営内で議論ののち、選択肢文がミスリーディングであると判断して、選択肢 1, 3, 4 の三つを選んだチームも正答としてカウントしています。誤解を招く表現で申し訳ございません。

問17

Git のデフォルト設定を使用している時、リポジトリに追加しない無視ファイルを記述できる場所を全て選べ。なお、 Git のバージョンは 2.47.0 とする。

選択肢(複数選択)

  1. .gitkeep
  2. .gitignore.local
  3. .git/config
  4. .git/info/ignore
  5. $GIT_DIR/exclude
  6. $HOME/.git/config
  7. $XDG_CONFIG_HOME/git/config
  8. $XDG_CONFIG_HOME/git/ignore

解説

man gitignore 5 によると、無視設定が読み込まれる場所は以下のとおりです。

  • .gitignore
  • $GIT_DIR/info/exclude
  • git-config の core.excludesFile で指定されたファイル
    • デフォルトは $XDG_CONFIG_HOME/git/ignore
    • $XDG_CONFIG_HOME が空の場合 $HOME/.config/git/ignore

選択肢の中でこの三つに含まれるのは 8 の $XDG_CONFIG_HOME/git/ignore のみです。

それ以外の選択肢についての解説は以下の通りです。

  • 1, 2, 4, 5 は、名前がそれっぽいが関係ない(または実在しない)ファイル
    • .gitkeep: 空ディレクトリを Git でトラックするために慣例的に用いられるファイル名
    • .gitignore.local: Git の仕様に含まれない、名前それっぽいだけのファイル
    • .git/info/ignore / $GIT_DIR/exclude: .git (または $GIT_DIR) 配下の info/exclude が正しい
  • 3, 7 は git-config ファイル
    • コンフィグに無視設定は直接記述できないので不適
  • 6 は名前が git-config っぽいだけの実在しないファイル
    • $HOME 全体をを Git 管理していれば実在しうるが、上記の通り git-config ファイルは不適

問18

問題文

fetchurl を使って GNU Hello 2.12.2 のソース (tar.gz) をダウンロードする Nix 式を作成したい。このとき以下に示す hello.nix において hash に当てはまる文字列の最初の10文字を記述せよ。ただし、ハッシュ方式は SHA-256 を使用し、ダウンロードサーバは https://ftp.gnu.org/gnu/hello/ とする。

以下は hello.nix の fetchurl 使用部分である。

  src = fetchurl {
    url = "";
    hash = "ここに入る文字列";
  };

解説

ハッシュ文字列は nix hash コマンドで計算できます。

$ curl -O https://ftp.gnu.org/gnu/hello/hello-2.12.2.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1141k  100 1141k    0     0   325k      0  0:00:03  0:00:03 --:--:--  325k

$ nix hash file hello-2.12.2.tar.gz
sha256-WpqZbcKSzCTc9BHO6H6S9qrluNE72caBm0x6nc4IGKs=

または、 Nix 式全体を作成して hash が空のまま nix-build を実行することで計算させられます。

$ cat default.nix
{
  pkgs ? import <nixpkgs> { },
}:

with pkgs;
stdenv.mkDerivation rec {
  pname = "hello";
  version = "2.12.2";

  src = fetchurl {
    url = "https://ftp.gnu.org/gnu/hello/hello-2.12.2.tar.gz";
    hash = "";
  };
}

$ nix-build
warning: found empty hash, assuming 'sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='
these 2 derivations will be built:
  /nix/store/vvs1m9azixlxk0m59rdlf3wa2cmv8nxm-hello-2.12.2.tar.gz.drv
  /nix/store/jryhi5l94d8b2v6ibqr9v7kdbwqx5ki4-hello-2.12.2.drv
building '/nix/store/vvs1m9azixlxk0m59rdlf3wa2cmv8nxm-hello-2.12.2.tar.gz.drv'...

trying https://ftp.gnu.org/gnu/hello/hello-2.12.2.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1141k  100 1141k    0     0   270k      0  0:00:04  0:00:04 --:--:--  285k
error: hash mismatch in fixed-output derivation '/nix/store/vvs1m9azixlxk0m59rdlf3wa2cmv8nxm-hello-2.12.2.tar.gz.drv':
         specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
            got:    sha256-WpqZbcKSzCTc9BHO6H6S9qrluNE72caBm0x6nc4IGKs=
error: 1 dependencies of derivation '/nix/store/jryhi5l94d8b2v6ibqr9v7kdbwqx5ki4-hello-2.12.2.drv' failed to build

この中から 先頭10文字 を取り出した sha256-Wpq が正答です。

問19

以下の Ansible インベントリを使用する際、ホスト 10.10.0.1 はいくつのグループに該当するか、整数で答えよ。なお、デフォルトグループは考慮せず、使用する Ansible のバージョンは 2.15.5 とする。

a:
  hosts:
    server:
      ansible_host: 10.10.0.1
  children:
    b:
      hosts:
        c:
          server:
    c:
      children:
        d:
      hosts: {"router":{"ansible_host":"10.0.10.1"},"children":{"g":{}}}

d:
  hosts:
    nfs:
      ansible_host: 10.10.1.1


e:
  children:
    b:
    d:

f:
  children:
    g:
    a:
  hosts:
    router:
    nfs:
    server:

解説

当該ホストはグループ a, f に所属するため、 2個が正答です。

  • ahosts 直下に server という名前で 10.10.0.1 ホストが記述されているので、当該ホストは a に所属する

  • achildren として記述されている b には、 server は所属しない

    • bhosts として cこれはグループではなく新しいホストである)が記述されており、またその直下に server というキーが存在するが、これは a で作成された server という名前のホストとは無関係である
      • ホスト定義の直下には ansible_host 等の設定(ホスト変数)が記述されるべきであり、ここにホスト名を置いても実在しない設定項目だと解釈されるため
  • b と同じく achildren として記述されている c には、server は所属しない

    • まず、cchildren として指定されている d には、後述するとおり server は所属しない
    • hosts の定義も server を含むような設定ではない
      • router ホストは server と異なる IP アドレスを持つため
      • children ホストに紐づけられた変数名 として g というキーが定義されているが、b と似た理由で、ここにグループ名を置いても実在しない設定項目だと解釈されるため
  • d には、server は所属しない

    • 無関係なホスト nfs が定義されているだけ
  • e には、server は所属しない

    • 2つの children として b, d が指定されているが、先述の通りいずれも server を含まない
  • f には、server が所属する

    • 2つの children として g, a が指定されているが、aserver を含むため f にも server が所属することになる
    • 3つの hosts として router, nfs, server が指定されているため、 server が所属することになる
    • server を含むことが重複して定義されていることになるが問題ない)
  • fchildren として記述されている g には、server は所属しない

    • 内容が空っぽであるため