はじめに
普段からUnix系のコマンドに慣れていると、Windowsでコマンドによる整形等やろうとしたときに四苦八苦することがよくあります。
最近ではWLS2もあるので、大分ハードルが低くなっていますが、仕事柄、複数のPCを使うことも多く、それぞれのPCで自分用の作業環境を作るのも面倒なので、Git等での管理も楽で簡単に環境構築出来るDockerで作ってみたので構築した環境を紹介したいと思います。
Dockerによる開発環境の構築
Linuxの環境を使うだけであれば、WindowsであればWLS2を使う、VirtualBoxで仮想マシンを作る等、最近は色々と選択肢がありますが、好きなパッケージ等入れて自分なりの環境を構築するまでにはそれなりに時間もかかり、複数のPCに同じ環境を用意しようとした場合は更に時間がかかります。
それに比べ、Dockerであれば、最初に作り込んだDockerfileを用意しておけば、Windowsでも、MacOSでも、Linuxでも同じように使用できること、そもそもDockerfileやDocker Composeのファイルはテキストのため、Git等で管理しやすいのが利点かと思います。
今回は、Windows端末にDocker Desktopをインストールし、作業用途のコンテナを構築してみようと思います。
作った環境
今回作成するコンテナ用のディレクトリ配下に以下のようにファイル等配置し、コンテナ作成しました。
| パス | 内容 |
|---|---|
| Dockerfile | Dockerファイル |
| docker-compose.yml | Docker Composeファイル |
| /config/zpreztorc | カスタム済みpreztoファイル |
| /config/agnoster.zsh-theme | カスタム済みpreztoファイル |
| /share/ | Windowsホスト側との共有用ディレクトリ |
| ~/.aws | Windowsホスト側で設定しているAWS CLI設定ファイルを使うため共有 |
Dockerfile
適当に使いそうなパッケージやツールを諸々入れました。
また、普段使っているMacOSではpreztoのagnosterというテーマを使って、過去コマンドの検索やシンタックスハイライト等の機能を使っているため、設定用のファイルを別で用意して、配置したファイルを上書きするようにしました。
MacOSやLinuxでの内容となりますが、preztoの詳細は以前書いた以下を参考にしてください。
ユーザについては今回自分しか使わない作業用なのでrootでの使用前提としています。
# ============================================================
# Dockerfile 設定
# ============================================================
FROM ubuntu:26.04
# ロケール・タイムゾーン設定
ENV TZ=Asia/Tokyo
ENV LANG=ja_JP.UTF-8
# ------------------------------------------------------------
# 基本パッケージのインストール
# ------------------------------------------------------------
RUN apt-get update && apt-get install -y \
# ロケール
locales \
tzdata \
# 基本ツール
curl \
git \
vim \
unzip \
zip \
# ビルドツール
build-essential \
make \
gcc \
g++ \
# zprezto
zsh \
# Ansible
ansible \
# その他の便利ツール
jq \
awscli \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# ロケール生成
RUN locale-gen ${LANG} && \
ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone
# ------------------------------------------------------------
# zprezto設定
# ------------------------------------------------------------
RUN git clone --recursive https://github.com/sorin-ionescu/prezto.git "/root/.zprezto"
COPY config/zpreztorc /root/.zprezto/runcoms/zpreztorc
COPY config/agnoster.zsh-theme /root/.zprezto/modules/prompt/external/agnoster/agnoster.zsh-theme
# ホームディレクトリにシンボリックリンク作成
# 参考:https://github.com/sorin-ionescu/prezto
SHELL ["/bin/zsh", "-c"]
RUN setopt EXTENDED_GLOB && \
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do \
ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"; \
done
# ------------------------------------------------------------
# tfenv設定
# ------------------------------------------------------------
RUN git clone https://github.com/tfutils/tfenv.git /root/.tfenv && \
/root/.tfenv/bin/tfenv install 1.15.7 && \
/root/.tfenv/bin/tfenv use 1.15.7 && \
cat << _EOF_ >> /root/.zshrc
# ============ カスタム設定 ============
export PATH=$HOME/.tfenv/bin:$PATH
_EOF_
# ------------------------------------------------------------
# デフォルトのシェルを zsh に設定
# ------------------------------------------------------------
RUN usermod -s /bin/zsh root
# コンテナ起動時に zsh を実行
CMD ["/bin/zsh"]
Docker Compose
今回の使用用途は基本的にjqによる整形や、Linuxコマンドでの作業用途なので、最低限の設定のみ行っています。
生成物をWindows側でも利用できるように、「/share」のみホスト側と共有し、その他のディレクトリは永続化していません。
AWSコマンドはホストとなるWindows側でも使うため、設定ファイル等格納される「~/.aws」をリードオンリーで共有するようにしています。
# ============================================================
# Docker Compose 設定
# ============================================================
services:
worklinux:
build: .
image: worklinux
hostname: worklinux
container_name: worklinux
restart: unless-stopped
tty: true
stdin_open: true
volumes:
- C:/Users/username/.aws:/root/.aws:ro
- C:/Users/username/share:/share
working_dir: /share
volumes:
worklinux-home:
driver: local
prezto設定ファイル
自分用にカスタマイズしたprezto関連のファイルを用意しておきます。
agnoster.zsh-themeの変更
デフォルトだとコンソールにユーザ名も表示されますが、今回はrootログインしか行わないため、ホスト名と現在のディレクトリのみ表示するようにしました。
また、後述のWindows Terminalで見栄えが良くなるよう、prompt_contextとprompt_dirの色指定部分をカスタマイズしています。
agnoster.zsh-theme(展開してください)
# vim:ft=zsh ts=2 sw=2 sts=2
#
# agnoster's Theme - https://gist.github.com/3712874
# A Powerline-inspired theme for ZSH
#
# # README
#
# In order for this theme to render correctly, you will need a
# [Powerline-patched font](https://gist.github.com/1595572).
#
# In addition, I recommend the
# [Solarized theme](https://github.com/altercation/solarized/) and, if you're
# using it on Mac OS X, [iTerm 2](http://www.iterm2.com/) over Terminal.app -
# it has significantly better color fidelity.
#
# # Goals
#
# The aim of this theme is to only show you *relevant* information. Like most
# prompts, it will only show git information when in a git working directory.
# However, it goes a step further: everything from the current user and
# hostname to whether the last call exited with an error to whether background
# jobs are running in this shell will all be displayed automatically when
# appropriate.
### Segments of the prompt, default order declaration
typeset -aHg AGNOSTER_PROMPT_SEGMENTS=(
prompt_status
prompt_context
prompt_virtualenv
prompt_dir
prompt_git
prompt_end
)
### Segment drawing
# A few utility functions to make it easy and re-usable to draw segmented prompts
CURRENT_BG='NONE'
if [[ -z "$PRIMARY_FG" ]]; then
PRIMARY_FG=black
fi
# Characters
SEGMENT_SEPARATOR="\ue0b0"
PLUSMINUS="\u00b1"
BRANCH="\ue0a0"
DETACHED="\u27a6"
CROSS="\u2718"
LIGHTNING="\u26a1"
GEAR="\u2699"
# Begin a segment
# Takes two arguments, background and foreground. Both can be omitted,
# rendering default background/foreground.
prompt_segment() {
local bg fg
[[ -n $1 ]] && bg="%K{$1}" || bg="%k"
[[ -n $2 ]] && fg="%F{$2}" || fg="%f"
if [[ $CURRENT_BG != 'NONE' && $1 != $CURRENT_BG ]]; then
print -n "%{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR%{$fg%}"
else
print -n "%{$bg%}%{$fg%}"
fi
CURRENT_BG=$1
[[ -n $3 ]] && print -n $3
}
# End the prompt, closing any open segments
prompt_end() {
if [[ -n $CURRENT_BG ]]; then
print -n "%{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR"
else
print -n "%{%k%}"
fi
print -n "%{%f%}"
CURRENT_BG=''
}
### Prompt components
# Each component will draw itself, and hide itself if no information needs to be shown
# Context: user@hostname (who am I and where am I)
prompt_context() {
local user=`whoami`
if [[ "$user" != "$DEFAULT_USER" || -n "$SSH_CONNECTION" ]]; then
#prompt_segment $PRIMARY_FG default " %(!.%{%F{yellow}%}.)$user@%m "
prompt_segment 'blue' default " %(!.%{%F{yellow}%}.)%m "
fi
}
# Git: branch/detached head, dirty status
prompt_git() {
local color ref
is_dirty() {
test -n "$(git status --porcelain --ignore-submodules)"
}
ref="$vcs_info_msg_0_"
if [[ -n "$ref" ]]; then
if is_dirty; then
color=yellow
ref="${ref} $PLUSMINUS"
else
color=green
ref="${ref} "
fi
if [[ "${ref/.../}" == "$ref" ]]; then
ref="$BRANCH $ref"
else
ref="$DETACHED ${ref/.../}"
fi
prompt_segment $color $PRIMARY_FG
print -n " $ref"
fi
}
# Dir: current working directory
prompt_dir() {
#prompt_segment blue $PRIMARY_FG ' %~ '
prompt_segment cyan black ' %~ '
}
# Status:
# - was there an error
# - am I root
# - are there background jobs?
prompt_status() {
local symbols
symbols=()
[[ $RETVAL -ne 0 ]] && symbols+="%{%F{red}%}$CROSS"
[[ $UID -eq 0 ]] && symbols+="%{%F{yellow}%}$LIGHTNING"
[[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="%{%F{cyan}%}$GEAR"
[[ -n "$symbols" ]] && prompt_segment $PRIMARY_FG default " $symbols "
}
# Display current virtual environment
prompt_virtualenv() {
if [[ -n $VIRTUAL_ENV ]]; then
color=cyan
prompt_segment $color $PRIMARY_FG
print -Pn " $(basename $VIRTUAL_ENV) "
fi
}
## Main prompt
prompt_agnoster_main() {
RETVAL=$?
CURRENT_BG='NONE'
for prompt_segment in "${AGNOSTER_PROMPT_SEGMENTS[@]}"; do
[[ -n $prompt_segment ]] && $prompt_segment
done
}
prompt_agnoster_precmd() {
vcs_info
PROMPT='%{%f%b%k%}$(prompt_agnoster_main) '
}
prompt_agnoster_setup() {
autoload -Uz add-zsh-hook
autoload -Uz vcs_info
prompt_opts=(cr subst percent)
add-zsh-hook precmd prompt_agnoster_precmd
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes false
zstyle ':vcs_info:git*' formats '%b'
zstyle ':vcs_info:git*' actionformats '%b (%a)'
}
prompt_agnoster_setup "$@"
zpreztorcの変更
gitやsyntax-highlighting、Autosuggestionsの機能を使用するため、モジュール設定を追加しています。
また、テーマをお気に入りのagnosterにするため、スタイル設定でテーマを指定しています。
zpreztorc(展開してください)
#
# Sets Prezto options.
#
# Authors:
# Sorin Ionescu <sorin.ionescu@gmail.com>
#
#
# General
#
# Set case-sensitivity for completion, history lookup, etc.
# zstyle ':prezto:*:*' case-sensitive 'yes'
# Color output (auto set to 'no' on dumb terminals).
zstyle ':prezto:*:*' color 'yes'
# Add additional directories to load prezto modules from
# zstyle ':prezto:load' pmodule-dirs $HOME/.zprezto-contrib
# Allow module overrides when pmodule-dirs causes module name collisions
# zstyle ':prezto:load' pmodule-allow-overrides 'yes'
# Set the Zsh modules to load (man zshmodules).
# zstyle ':prezto:load' zmodule 'attr' 'stat'
# Set the Zsh functions to load (man zshcontrib).
# zstyle ':prezto:load' zfunction 'zargs' 'zmv'
# Set the Prezto modules to load (browse modules).
# The order matters.
zstyle ':prezto:load' pmodule \
'environment' \
'terminal' \
'editor' \
'history' \
'directory' \
'spectrum' \
'utility' \
'git' \
'completion' \
'syntax-highlighting' \
'history-substring-search' \
'autosuggestions' \
'prompt'
#
# Autosuggestions
#
# Set the query found color.
# zstyle ':prezto:module:autosuggestions:color' found ''
#
# Completions
#
# Set the entries to ignore in static '/etc/hosts' for host completion.
# zstyle ':prezto:module:completion:*:hosts' etc-host-ignores \
# '0.0.0.0' '127.0.0.1'
#
# Editor
#
# Set the characters that are considered to be part of a word.
# zstyle ':prezto:module:editor' wordchars '*?_-.[]~&;!#$%^(){}<>'
# Set the key mapping style to 'emacs' or 'vi'.
zstyle ':prezto:module:editor' key-bindings 'emacs'
# Auto convert .... to ../..
# zstyle ':prezto:module:editor' dot-expansion 'yes'
# Allow the zsh prompt context to be shown.
#zstyle ':prezto:module:editor' ps-context 'yes'
#
# Git
#
# Ignore submodules when they are 'dirty', 'untracked', 'all', or 'none'.
# zstyle ':prezto:module:git:status:ignore' submodules 'all'
#
# GNU Utility
#
# Set the command prefix on non-GNU systems.
# zstyle ':prezto:module:gnu-utility' prefix 'g'
#
# History
#
# Set the file to save the history in when an interactive shell exits.
# zstyle ':prezto:module:history' histfile "${ZDOTDIR:-$HOME}/.zsh_history"
# Set the maximum number of events stored in the internal history list.
# zstyle ':prezto:module:history' histsize 10000
# Set the maximum number of history events to save in the history file.
# zstyle ':prezto:module:history' savehist 10000
#
# History Substring Search
#
# Set the query found color.
# zstyle ':prezto:module:history-substring-search:color' found ''
# Set the query not found color.
# zstyle ':prezto:module:history-substring-search:color' not-found ''
# Set the search globbing flags.
# zstyle ':prezto:module:history-substring-search' globbing-flags ''
# Enable search case-sensitivity.
# zstyle ':prezto:module:history-substring-search' case-sensitive 'yes'
# Enable search for fuzzy matches.
# zstyle ':prezto:module:history-substring-search' fuzzy 'yes'
# Enable search uniqueness.
# zstyle ':prezto:module:history-substring-search' unique 'yes'
# Enable prefixed search.
# zstyle ':prezto:module:history-substring-search' prefixed 'yes'
#
# macOS
#
# Set the keyword used by `mand` to open man pages in Dash.app
# zstyle ':prezto:module:osx:man' dash-keyword 'manpages'
#
# Pacman
#
# Set the Pacman frontend.
# zstyle ':prezto:module:pacman' frontend 'yaourt'
#
# Prompt
#
# Set the prompt theme to load.
# Setting it to 'random' loads a random theme.
# Auto set to 'off' on dumb terminals.
zstyle ':prezto:module:prompt' theme 'agnoster'
# Set the working directory prompt display length.
# By default, it is set to 'short'. Set it to 'long' (without '~' expansion)
# for longer or 'full' (with '~' expansion) for even longer prompt display.
# zstyle ':prezto:module:prompt' pwd-length 'short'
# Set the prompt to display the return code along with an indicator for non-zero
# return codes. This is not supported by all prompts.
# zstyle ':prezto:module:prompt' show-return-val 'yes'
#
# Python
#
# Auto switch the Python virtualenv on directory change.
# zstyle ':prezto:module:python:virtualenv' auto-switch 'yes'
# Automatically initialize virtualenvwrapper if pre-requisites are met.
# zstyle ':prezto:module:python:virtualenv' initialize 'yes'
#
# Ruby
#
# Auto switch the Ruby version on directory change.
# zstyle ':prezto:module:ruby:chruby' auto-switch 'yes'
#
# Screen
#
# Auto start a session when Zsh is launched in a local terminal.
# zstyle ':prezto:module:screen:auto-start' local 'yes'
# Auto start a session when Zsh is launched in a SSH connection.
# zstyle ':prezto:module:screen:auto-start' remote 'yes'
#
# SSH
#
# Set the SSH identities to load into the agent.
# zstyle ':prezto:module:ssh:load' identities 'id_rsa' 'id_rsa2' 'id_github'
#
# Syntax Highlighting
#
# Set syntax highlighters.
# By default, only the main highlighter is enabled.
# zstyle ':prezto:module:syntax-highlighting' highlighters \
# 'main' \
# 'brackets' \
# 'pattern' \
# 'line' \
# 'cursor' \
# 'root'
#
# Set syntax highlighting styles.
# zstyle ':prezto:module:syntax-highlighting' styles \
# 'builtin' 'bg=blue' \
# 'command' 'bg=blue' \
# 'function' 'bg=blue'
#
# Set syntax pattern styles.
# zstyle ':prezto:module:syntax-highlighting' pattern \
# 'rm*-rf*' 'fg=white,bold,bg=red'
#
# Terminal
#
# Auto set the tab and window titles.
# zstyle ':prezto:module:terminal' auto-title 'yes'
# Set the window title format.
# zstyle ':prezto:module:terminal:window-title' format '%n@%m: %s'
# Set the tab title format.
# zstyle ':prezto:module:terminal:tab-title' format '%m: %s'
# Set the terminal multiplexer title format.
# zstyle ':prezto:module:terminal:multiplexer-title' format '%s'
#
# Tmux
#
# Auto start a session when Zsh is launched in a local terminal.
# zstyle ':prezto:module:tmux:auto-start' local 'yes'
# Auto start a session when Zsh is launched in a SSH connection.
# zstyle ':prezto:module:tmux:auto-start' remote 'yes'
# Integrate with iTerm2.
# zstyle ':prezto:module:tmux:iterm' integrate 'yes'
# Set the default session name:
# zstyle ':prezto:module:tmux:session' name 'YOUR DEFAULT SESSION NAME'
#
# Utility
#
# Enabled safe options. This aliases cp, ln, mv and rm so that they prompt
# before deleting or overwriting files. Set to 'no' to disable this safer
# behavior.
# zstyle ':prezto:module:utility' safe-ops 'yes'
Dockerの作成
PowerShellやCmdを起動し、Dockerfile等を配置したディレクトリで以下実行します。
docker compose up -d
起動したら接続出来るか確認してみます。
今回はworklinuxという名前でコンテナを作成したので、以下のように実行します。
docker exec -it worklinux /bin/zsh
問題なく接続できれば、今回の場合、以下のような表示となるはずです。
Windows Terminal設定
Windows TerminalでDockerに接続するための設定を行っていきます。
Docker接続用プロファイルの作成
Windows Terminalの「設定」から「新しいプロファイルを追加します」で「新しい空のプロファイル」を選択し、以下のように必要な設定を行います。
| 項目 | 設定 | 備考 |
|---|---|---|
| 名前 | Docker worklinux | 任意の名前を指定 |
| コマンドライン | C:\Program Files\Docker\Docker\resources\bin\docker.exe exec -it worklinux /bin/zsh |
dockerコマンドのパスを指定 |
その他の設定は自分好みに設定してください。
コマンドラインには、docker.exeのパスを指定して、コマンドを後ろに記載することで、PowerShell等でdocker execコマンドを実行しなくても直接コンテナに接続することができるため、上記のように指定します。
タブ起動時接続設定
「設定」→「スタートアップ」の「規定のプロファイル」で先ほど作成したDocker接続用プロファイルを選択して保存します。
変更後、Windows Terminalを立ち上げ直したり、新しいタブを開くと、直接コンテナのプロンプトが立ち上がります。
Nerd Fontのインストール
先ほどインストールしたzpreztoでは、Git管理されたディレクトリに移動すると現在のブランチをプロンプト上で示すモジュールが実装されておりますが、一部特殊なアイコンが使われているため、Windows Terminalで表示すると、以下のように文字化けしてしまいます。(masterの左のアイコン)
機能的には問題ないので、そのまま使い続けてもいいのですが、せっかくなので、きちんと表示できるようにしようと思います。
以下のMicrosoftの公式ドキュメントに、特殊文字を表示するために必要となるNerd Fontのインストール例が紹介されているため、Nerd Fontのページからフォントをダウンロードします。
Nerd Fontのページを開くと、各種フォント用のNerd Fontが用意されているため、今回は、Windows Terminalでもデフォルトフォントとして設定されている「Cascadia Mono」用となる「CaskaydiaMono Nerd Font」をダウンロードします。
ダウンロードしたZipファイルを解凍したら、.ttfファイルのみを選択して「インストール」を行います。
先程の公式ドキュメントには他にもチュートリアルが色々書かれていますが、今回はフォントのインストールだけでOKです。
Nerd Fontの指定
Windows Terminalに戻り、先程作成したプロファイルを選択し、「外観」の「フォント フェイス」をクリックします。
デフォルトでは「Cascadia Mono」が選択されているはずなので、先程インストールした「CaskaydiaMono Nerd Font」を選択して、「保存」します。
コンテナに接続し、Git管理のディレクトリに移動すると、先程は文字化けアイコンだったGitブランチアイコンが先ほどと異なっていることが確認できるかと思います。
AWS Identity Center認証によるAWS CLI実行
急に内容が変わりますが、コンテナ内からIdentity Center認証を行う場合、そのままでは認証を通せないため以下で手順を紹介します。
Identity Centerの一時トークンを使用する場合、最初に以下コマンドでIdentity Centerへログインする必要があります。
aws sso login --profile [プロファイル名]
実行すると、Webブラウザが立ち上がり、Identity Centerのユーザーでログインすることで、一時トークンが払い出され、コマンド実行ができるようになります。
ただ、aws sso loginをコンテナ内で行うと、コンテナ内で(今回の構成では)Webブラウザが起動できないため、失敗してしまいます。
aws sso loginで払い出された一時トークンは、docker-compose.ymlで共有設定した「C:/Users/username/.aws」配下に出力されることから、Identity Centerの一時トークンを使用する場合は、Windowsホスト側でaws sso loginを実行&一時トークンを払い出した後、コンテナ内でIdentity Centerのプロファイルを指定することでコマンド実行できるので、参考にしてください。
おわりに
今回WindowsでDockerをシームレスに使用するための設定を行いましたが、最初に自分が思っていた以上に、使える構成に仕上がったと思います。
今までWLS2、VirtualBox等、様々な仮想環境を使ってきましたが、単純に作業用途で使うなら、ホスト側OSを選ばないDockerはアリだなと感じました。







