Skip to content

Commit eb38ae1

Browse files
committed
Add zsh support and docs
1 parent c052b02 commit eb38ae1

File tree

7 files changed

+135
-60
lines changed

7 files changed

+135
-60
lines changed

Dockerfile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ FROM ubuntu:noble-20250714
66
RUN apt-get update && apt-get install -y --no-install-recommends \
77
build-essential \
88
busybox \
9+
ca-certificates \
910
curl \
1011
gdb \
1112
git \
1213
man-db \
13-
ssh-client
14+
ssh-client \
15+
zsh
16+
17+
# Add oh my zsh
18+
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
1419

1520
# Use busybox to provide any missing commands
1621
# This is useful for commands like `telnet` that are not available in the base image
@@ -25,8 +30,8 @@ ENV USER_TERMINAL_CONFIG=/user-terminal-config
2530
# This can be overridden by the user mounting a different folder over the top
2631
RUN /root/terminal-config/ensure-user-terminal-config.sh && \
2732
ln -fs $USER_TERMINAL_CONFIG/inputrc /root/.inputrc && \
28-
echo 'source ${USER_TERMINAL_CONFIG}/bashrc' >> /root/.bashrc && \
29-
echo 'source ${USER_TERMINAL_CONFIG}/zshrc' >> /root/.zshrc
33+
ln -fs $USER_TERMINAL_CONFIG/bashrc /root/.bash_aliases && \
34+
echo 'source ${USER_TERMINAL_CONFIG}/zshrc' > /root/.zshrc
3035

3136
# Install uv using the official image
3237
# See https://docs.astral.sh/uv/guides/integration/docker/#installing-uv

README.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,76 @@
11
# ubuntu-devcontainer
2-
Opinionated Ubuntu based devcontainer for python and EPICS development
2+
3+
Opinionated Ubuntu based devcontainer for python and EPICS development, tagged in step with upstream ubuntu for runtime.
4+
5+
Features:
6+
- User customisable bash/zsh environment
7+
- Cross container persistent shell history
8+
- git, curl make and other build-essentials
9+
- uv for python environment management
10+
- ssh, gdb and busybox for runtime debugging
11+
12+
## How to use from the commandline
13+
14+
To try it out without persistent shell history:
15+
16+
```bash
17+
podman run -it ghcr.io/diamondlightsource/ubuntu-devcontainer
18+
```
19+
20+
To keep the history and allow shell customisation:
21+
22+
```bash
23+
mkdir -p $HOME/.config/terminal-config
24+
podman run --mount type=bind,src=$HOME/.config/terminal-config,target=/user-terminal-config -it ghcr.io/diamondlightsource/ubuntu-devcontainer
25+
```
26+
27+
To do the above but with zsh:
28+
29+
```bash
30+
mkdir -p $HOME/.config/terminal-config
31+
podman run --mount type=bind,src=$HOME/.config/terminal-config,target=/user-terminal-config -it ghcr.io/diamondlightsource/ubuntu-devcontainer zsh
32+
```
33+
34+
## How to customize your shell
35+
36+
When mounting in `$HOME/.config/terminal-config`, the container will create the following files in the directory:
37+
- `bashrc`: loading some bash defaults
38+
- `zshrc`: loading some zsh defaults
39+
- `inputrc`: to customize the behaviour of up arrow etc in both shells
40+
41+
You are free to edit any of these files, adding overrides before or after the loading of the defaults, or even removing the loading of the defaults altogether.
42+
43+
History is also stored in this directory, in `.bash_eternal_history` and `.zsh_eternal_history` respectively.
44+
45+
## How to use as a devcontainer
46+
47+
See [this repo's `.devcontainer.json`](./.devcontainer.json) for an example on how to use as a devcontainer. Or clone this repo, open in vscode and click "reopen in container"
48+
49+
## How to use in the build stage of a Dockerfile
50+
51+
If you are using this during the build stage of a Dockerfile, then you should select the upstream `ubuntu` container for the runtime.
52+
53+
For instance:
54+
55+
```Dockerfile
56+
# The developer stage is used as a devcontainer including dev versions
57+
# of the build dependencies
58+
FROM ghcr.io/diamondlightsource/ubuntu-devcontainer:noble AS developer
59+
RUN apt-get update -y && apt-get install -y --no-install-recommends \
60+
libevent-dev \
61+
libreadline-dev
62+
63+
# The build stage makes some assets using the developer tools
64+
FROM developer AS build
65+
RUN my-build-script.sh /assets
66+
67+
# The runtime stage installs runtime deps then copies in built assets
68+
# This time we remove the apt lists to save disk space
69+
FROM ubuntu:noble as runtime
70+
RUN apt-get update -y && apt-get install -y --no-install-recommends \
71+
libevent \
72+
libreadline \
73+
&& rm -rf /var/lib/apt/lists/*
74+
COPY --from=build /assets /
75+
```
76+

terminal-config/bashrc-default

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
#!/bin/bash
22

3-
# default opinioned bash configuration to be sourced from user's bashrc
4-
5-
# enable enternal shared history
6-
export HISTCONTROL=ignoreboth:erasedups
7-
export HISTSIZE=-1
8-
export HISTFILESIZE=-1
9-
export SAVEHIST=-1
10-
export HISTFILE=$USER_TERMINAL_CONFIG/.bash_eternal_history
11-
export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
12-
13-
# bash theme - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/dst.zsh-theme
3+
# bash theme - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
144
# from https://github.com/devcontainers/features/blob/main/src/common-utils/scripts/bash_theme_snippet.sh
155
__bash_prompt() {
166
local userpart='`export XIT=$? \
177
&& echo -n "\u " \
188
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
199
local gitbranch='`\
20-
export BRANCH="$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null)"; \
21-
if [ "${BRANCH:-}" != "" ]; then \
22-
echo -n "\[\033[0;36m\](\[\033[1;32m\]${BRANCH:-}" \
23-
&& if git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
24-
echo -n " \[\033[1;33m\]✗"; \
25-
fi \
26-
&& echo -n "\[\033[0;36m\]) "; \
27-
fi`'
10+
export BRANCH="$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null)"; \
11+
if [ "${BRANCH:-}" != "" ]; then \
12+
echo -n "\[\033[0;36m\](\[\033[1;32m\]${BRANCH:-}" \
13+
&& if git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
14+
echo -n " \[\033[1;33m\]✗"; \
15+
fi \
16+
&& echo -n "\[\033[0;36m\]) "; \
17+
fi`'
2818
local removecolor='\[\033[0m\]'
2919
local lightblue='\[\033[1;34m\]'
3020
local cyan='\[\033[0;36m\]'
@@ -34,23 +24,16 @@ __bash_prompt() {
3424
__bash_prompt
3525
export PROMPT_DIRTRIM=4
3626

37-
# Set the default git editor if not already set
38-
# from https://github.com/devcontainers/features/blob/f8e7e275b7ba2808e14a035afd753b83be68e2d9/src/common-utils/scripts/rc_snippet.sh
39-
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
40-
if [ "${TERM_PROGRAM}" = "vscode" ]; then
41-
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
42-
export GIT_EDITOR="code-insiders --wait"
43-
else
44-
export GIT_EDITOR="code --wait"
45-
fi
46-
fi
47-
fi
48-
49-
# colorize ls output
50-
export LS_OPTIONS='--color=auto'
51-
eval "$(dircolors)"
52-
alias ls='ls $LS_OPTIONS'
53-
alias ll='ls $LS_OPTIONS -l'
27+
# enable enternal shared history
28+
export HISTCONTROL=ignoreboth:erasedups
29+
export HISTSIZE=-1
30+
export HISTFILESIZE=-1
31+
export SAVEHIST=-1
32+
export HISTFILE=$USER_TERMINAL_CONFIG/.bash_eternal_history
33+
export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
5434

5535
# enable bash completion for git
5636
source /usr/share/bash-completion/completions/git
37+
38+
# Setup some common defaults like vscode for the git editor
39+
source "$HOME/terminal-config/common-defaults"

terminal-config/bashrc-template

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#!/bin/bash
22

3-
# This bashrc will be source from /root/.bashrc upon launch of every terminal
4-
# in a devcontainer that uses the bash-config feature from
5-
# https://github.com/DiamondLightSource/devcontainer-features
3+
# This bashrc will be sourced from /root/.bashrc upon launch of every terminal
4+
# in a devcontainer that uses the ubuntu-devcontainer as a base
5+
# https://github.com/DiamondLightSource/ubuntu-devcontainer
66

7-
# This file is initialized by bash-config, but you are then free to edit it
7+
# This file is initialized by the devcontainer, but you are then free to edit it
88

9-
# execute default, opinionated settings - delete this line to remove defaults
9+
# Execute default, opinionated settings:
10+
# https://github.com/DiamondLightSource/ubuntu-devcontainer/blob/main/terminal-config/bashrc-default
11+
# delete this line to remove defaults
1012
source ~/terminal-config/bashrc-default
1113

1214
if [ ! -f ~/one-time ]; then

terminal-config/common-defaults

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Set the default git editor if not already set
2+
# from https://github.com/devcontainers/features/blob/f8e7e275b7ba2808e14a035afd753b83be68e2d9/src/common-utils/scripts/rc_snippet.sh
3+
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
4+
if [ "${TERM_PROGRAM}" = "vscode" ]; then
5+
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
6+
export GIT_EDITOR="code-insiders --wait"
7+
else
8+
export GIT_EDITOR="code --wait"
9+
fi
10+
fi
11+
fi

terminal-config/zshrc-default

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#!/bin/zsh
22

3-
# This zshrc will be source from /root/.zshrc upon launch of every terminal
4-
# in a devcontainer that uses the bash-config feature from
5-
# https://github.com/DiamondLightSource/devcontainer-features
3+
# Set the prompt theme to robbyrussell if not already set
4+
ZSH_THEME=${ZSH_THEME:-robbyrussell}
65

7-
# This file is initialized by vscode feature bash-config,
8-
# but you are then free to edit it
6+
# Source oh my zsh, theme and plugins must be set before this
7+
source "$HOME/.oh-my-zsh/oh-my-zsh.sh"
98

10-
# set up eternal history for zsh
9+
# Set up eternal history for zsh
1110
HISTCONTROL=ignoreboth:erasedups
1211
HISTSIZE=10000000
1312
SAVEHIST=$HISTSIZE
14-
HISTFILE=$CONFIG_FOLDER/.zsh_eternal_history
13+
HISTFILE=$USER_TERMINAL_CONFIG/.zsh_eternal_history
1514
setopt BANG_HIST # Treat the '!' character specially during expansion.
1615
setopt EXTENDED_HISTORY # Write the history file in the ":start:elapsed;command" format.
1716
setopt INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits.
@@ -24,7 +23,6 @@ setopt HIST_IGNORE_SPACE # Don't record an entry starting with a space.
2423
setopt HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file.
2524
setopt HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry.
2625
setopt HIST_VERIFY # Don't execute immediately upon history expansion.
27-
#setopt HIST_BEEP # Beep when accessing nonexistent history.
2826

29-
# set a theme compatible with vscode terminals
30-
ZSH_THEME="dst"
27+
# Setup some common defaults like vscode for the git editor
28+
source "$HOME/terminal-config/common-defaults"

terminal-config/zshrc-template

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#!/bin/zsh
22

3-
# This zshrc will be source from /root/.zshrc upon launch of every terminal
4-
# in a devcontainer that uses the bash-config feature from
5-
# https://github.com/DiamondLightSource/devcontainer-features
3+
# This zshrc will be sourced from /root/.zshrc upon launch of every terminal
4+
# in a devcontainer that uses the ubuntu-devcontainer as a base
5+
# https://github.com/DiamondLightSource/ubuntu-devcontainer
66

7-
# This file is initialized by bash-config, but you are then free to edit it
7+
# This file is initialized by the devcontainer, but you are then free to edit it
88

9-
# execute default, opinionated settings - delete this line to remove defaults
9+
# Execute default, opinionated settings:
10+
# https://github.com/DiamondLightSource/ubuntu-devcontainer/blob/main/terminal-config/zshrc-default
11+
# delete this line to remove defaults
1012
source ~/terminal-config/zshrc-default
1113

1214
if [ ! -f ~/one-time ]; then

0 commit comments

Comments
 (0)