This commit is contained in:
Chuck Lantz 2020-08-09 17:08:06 -07:00
Родитель c840fb0bc2
Коммит 202fae4ba5
14 изменённых файлов: 404 добавлений и 204 удалений

Просмотреть файл

@ -1,20 +1,27 @@
# Development Container Scripts
This folder contains a set of scripts that can be referenced by Dockerfiles in development container "definitions" that are found under the [`containers` directory](../containers). When referenced properly, a hash is generated upon release that ensures that only the expected version of this script is executed. See [this Dockerfile](../container-templates/dockerfile/.devcontainer/Dockerfile) for an example.
This folder contains a set of scripts that can be referenced by Dockerfiles in development container "definitions" that are found under the [`containers` directory](../containers). You are also free to use them in your own dev container configurations.
The `test` sub-folder includes Debian, Alpine, and RedHat based dev containers that can be used to test the scripts.
See [CONTRIBUTING.md](../CONTRIBUTING.md) for details on contributing definitions to this repository.
## Scripts
- `common-debian.sh`, `common-alpine.sh`, `common-redhat.sh` - Installs common packages and utilities, creates a non-root user, and optionally upgrades packages, and installs zsh and Oh My Zsh!
- `docker-debian.sh`, `docker-redhat.sh` - Installs the Docker CLI and wires up a script that can enable non-root access to the Docker socket. See [Docker from Docker](../containers/docker-from-docker) for an example. Generally assumes `common-debian.sh` has been run.
- `node-debian.sh` - Installs the [Node Version Manager](https://github.com/nvm-sh/nvm) (nvm), the specified version of Node.js (if any) using nvm, ensures the specified non-root user can access everything. See [.NET Core](../containers/dotnet) for an example. Generally assumes `common-debian.sh` has been run.
Script names end in the Linux distribution "tree" they support.
- `-debian` - Debian or Ubuntu
- `-redhat` - CentOS, RHEL, Oracle Linux
- `-alpine` - Alpine Linux
| Script | Arguments | Purpose |
|--------|---------|-----------|
| `common-debian.sh`<br />`common-alpine.sh`<br />`common-redhat.sh` | `[INSTALL ZSH FLAG] [USERNAME] [USER UID] [USER GID] [UPGRADE PACKAGES FLAG]`<br /><br /> Defaults to `true vscode 1000 1000 true`. Set `USERNAME` to `none` to skip setting up a non-root user. | Installs common packages and utilities, creates a non-root user, and optionally upgrades packages, and installs zsh and Oh My Zsh! |
| `docker-debian.sh`<br />`docker-redhat.sh` | `[ENABLE NON-ROOT ACCESS] [SOURCE SOCKET] [TARGET SOCKET] [USERNAME]`<br /><br /> Defaults to `true /var/run/docker-host.sock /var/run/docker.sock vscode`. Only sets up `USERNAME` if the user exists on the system.| Installs the Docker CLI and wires up a script that can enable non-root access to the Docker socket. See the [docker-from-docker](../containers/docker-from-docker) definition for an example. |
| `node-debian.sh` | `[NVM INSTALL DIRECTORY] [NODE VERSION TO INSTALL] [USERNAME]`<br /><br />Defaults to `/usr/local/share/nvm lts/* vscode`. Only sets up `USERNAME` if the user exists on the system. | Installs the [Node Version Manager](https://github.com/nvm-sh/nvm) (nvm), the specified version of Node.js (if any) using nvm, ensures the specified non-root user can access everything. See the [dotnetcore](../containers/dotnetcore) definition for an example. |
| `maven-debian.sh` | `<MAVEN VERSION> [MAVEN INSTALL DIRECTORY] [USERNAME] [DOWNLOAD SHA512]`<br /><br />`MAVEN VERSION` is required. Other arguments default to `/usr/local/share/maven vscode dev-mode`. Only sets up `USERNAME` if the user exists on the system. Download checksum is skipped if set to `dev-mode`. | Installs [Apache Maven](https://github.com/nvm-sh/nvm) and ensures the specified non-root user can access everything. See the [java](../containers/java) definition for an example. |
| `gradle-debian.sh` | `<GRADLE VERSION> [GRADLE INSTALL DIRECTORY] [USERNAME] [DOWNLOAD SHA256]`<br /><br />`GRADLE VERSION` is required. Other arguments default to `/usr/local/share/gradle vscode no-check`. Only sets up `USERNAME` if the user exists on the system. Download checksum is skipped if set to `no-check`. | Installs the [Gradle](https://github.com/nvm-sh/nvm) and ensures the specified non-root user can access everything. See the [java](../containers/java) definition for an example. |
## Using a script
### Copying the script to .devcontainer/library-scripts
The easiest way to use a script is to simply copy it into a `.devcontainers/library-scripts` folder. From here you can then use the script as follows in your `Dockerfile`:
@ -23,17 +30,22 @@ The easiest way to use a script is to simply copy it into a `.devcontainers/libr
```Dockerfile
COPY library-scripts/*.sh /tmp/library-scripts/
RUN apt-get update \
&& /bin/bash /tmp/library-scripts/common-debian.sh \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
RUN /tmp/library-scripts/common-debian.sh
```
Generally it's also good to clean up after running a script in the same `RUN` statement to keep the "layer" small.
```Dockerfile
COPY library-scripts/*.sh /tmp/library-scripts/
RUN /tmp/library-scripts/common-debian.sh
&& apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
```
**Alpine**
```Dockerfile
COPY library-scripts/*.sh /tmp/library-scripts/
RUN apk update \
&& /bin/ash /tmp/library-scripts/common-alpine.sh \
RUN /bin/ash /tmp/library-scripts/common-alpine.sh \
&& rm -rf /tmp/library-scripts
```
@ -45,22 +57,27 @@ RUN /bin/bash /tmp/library-scripts/common-redhat.sh \
&& yum clean all && rm -rf /tmp/library-scripts
```
The last line is technically optional, but minimizes the size of the layer by removing temporary contents.
The CI process for this repository will automatically keep scripts in the `.devcontainers/library-scripts` folder up to date for each definition in the `containers` folder.
Note that the CI process for this repository will automatically keep scripts in the `.devcontainers/library-scripts` folder up to date for each definition in the `containers` folder.
### Downloading the script with curl instead
If you prefer, you can download the script using `curl` or `wget` and execute it instead. This can convienent to do with your own `Dockerfile`, but is generally avoided for definitions in this repository. To avoid unexpected issues, you should reference a release specific version of the script, rather than using master. For example:
If you prefer, you can download the script using `curl` or `wget` and execute it instead. This can convenient to do with your own `Dockerfile`, but is generally avoided for definitions in this repository. To avoid unexpected issues, you should reference a release specific version of the script, rather than using master. For example:
```Dockerfile
RUN curl -sSL -o- "https://github.com/microsoft/vscode-dev-containers/blob/v0.131.0/script-library/common-debian.sh" | bash -
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
```
Or if you're not sure if `curl` is installed:
```Dockerfile
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends curl ca-certificates \
&& curl -sSL -o- "https://github.com/microsoft/vscode-dev-containers/blob/v0.131.0/script-library/common-debian.sh" | bash - \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
```
The last line is technically optional, but minimizes the size of the layer by removing temporary contents.
As before, the last line is technically optional, but minimizes the size of the layer by removing temporary contents.
### Arguments
@ -75,9 +92,8 @@ In this case, you can simply pass in the arguments to the script.
ARG INSTALL_ZSH="true"
COPY library-scripts/*.sh /tmp/library-scripts/
RUN apt-get update \
&& /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "vscode" "1000" "1000" "true" \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
RUN /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "vscode" "1000" "1000" "true" \
&& apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
```
#### Using arguments when downloading with curl
@ -92,43 +108,12 @@ ARG INSTALL_ZSH="true"
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends curl ca-certificates \
&& curl -sSL -o- "https://github.com/microsoft/vscode-dev-containers/blob/v0.131.0/script-library/common-debian.sh" | bash -s -- "${INSTALL_ZSH}" "vscode" "1000" "1000" "true" \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
```
### [Optional] Validating a file's checksum for security when using curl
## Contributing
If for some reason you cannot copy the script you want to use into the `.devcontainer/library-scripts` folder, you can improve security using a checksum. The CI process will automatically generate a checksum on release if you add two related `ARG`s that end in `_SCRIPT_SOURCE` and `_SCRIPT_SHA`.
For example:
```Dockerfile
# Options for script
ARG INSTALL_ZSH="true"
# Script source
ARG COMMON_SCRIPT_SOURCE="https://github.com/microsoft/vscode-dev-containers/blob/v0.131.0/script-library/common-debian.sh"
ARG COMMON_SCRIPT_SHA="dev-mode"
# Download script, validate its checksum, and run it with the options above
RUN apt-get update \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends curl ca-certificates 2>&1 \
&& curl -sSL ${COMMON_SCRIPT_SOURCE} -o /tmp/common-setup.sh \
&& ([ "${COMMON_SCRIPT_SHA}" = "dev-mode" ] || (echo "${COMMON_SCRIPT_SHA} */tmp/common-setup.sh" | sha256sum -c -)) \
&& /bin/bash /tmp/common-setup.sh "${INSTALL_ZSH}" "vscode" "1000" "1000" "true" \
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/common-setup.sh
```
When a release is created, the SHA will be automatically added to the tagged source code. e.g. in v1.30.0, these updates are applied:
```Dockerfile
ARG COMMON_SCRIPT_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/v0.130.0/script-library/common-debian.sh"
ARG COMMON_SCRIPT_SHA="a6bfacc5c9c6c3706adc8788bf70182729767955b7a5509598ac205ce6847e1e"
```
This locks the version of the script to v1.30.0 and will verify that the script has not been modified before running it.
Check out the [v1.30.0 tag for the Ubuntu definition](https://github.com/microsoft/vscode-dev-containers/blob/v0.130.0/containers/ubuntu/.devcontainer/base.Dockerfile) to see a real world example of the script doing this for you.
See [CONTRIBUTING.md](../CONTRIBUTING.md) for details on contributing definitions to this repository.
## License

Просмотреть файл

@ -6,15 +6,15 @@
# Syntax: ./common-alpine.sh <install zsh flag> <username> <user UID> <user GID>
set -e
INSTALL_ZSH=${1:-"true"}
USERNAME=${2:-"$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)"}
USER_UID=${3:-1000}
USER_GID=${4:-1000}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" before running the script.'
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

Просмотреть файл

@ -4,28 +4,18 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
# Syntax: ./common-debian.sh <install zsh flag> <username> <user UID> <user GID> <upgrade packages flag>
apt-get-update-if-needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
set -e
# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag]
INSTALL_ZSH=${1:-"true"}
USERNAME=${2:-"$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)"}
USERNAME=${2:-"vscode"}
USER_UID=${3:-1000}
USER_GID=${4:-1000}
UPGRADE_PACKAGES=${5:-"true"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" in your Dockerfile before running the script.'
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
@ -47,6 +37,17 @@ fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Function to call apt-get if needed
apt-get-update-if-needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
apt-get-update-if-needed
@ -132,10 +133,10 @@ else
fi
# Add add sudo support for non-root user
if [ "${NON_ROOT_USER}" != "${USERNAME}" ]; then
if [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
NON_ROOT_USER="${USERNAME}"
EXISTING_NON_ROOT_USER="${USERNAME}"
fi
# Ensure ~/.local/bin is in the PATH for root and non-root users for bash. (zsh is later)
@ -149,12 +150,14 @@ fi
if [ "${INSTALL_ZSH}" = "true" ] && [ ! -d "/root/.oh-my-zsh" ] && [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
apt-get-update-if-needed
apt-get install -y zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
curl -fsSLo- https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh | bash 2>&1
echo "export PATH=\$PATH:\$HOME/.local/bin" >> /root/.zshrc
cp -R /root/.oh-my-zsh /home/$USERNAME
cp /root/.zshrc /home/$USERNAME
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
if [ "${USERNAME}" != "root" ]; then
cp -fR /root/.oh-my-zsh /home/$USERNAME
cp -f /root/.zshrc /home/$USERNAME
sed -i -e "s/\/root\/.oh-my-zsh/\/home\/$USERNAME\/.oh-my-zsh/g" /home/$USERNAME/.zshrc
chown -R $USER_UID:$USER_GID /home/$USERNAME/.oh-my-zsh /home/$USERNAME/.zshrc
fi
ZSH_ALREADY_INSTALLED="true"
fi
@ -163,6 +166,6 @@ mkdir -p "$(dirname "${MARKER_FILE}")"
echo -e "\
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
NON_ROOT_USER=${NON_ROOT_USER}\n\
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
DOT_LOCAL_ALREADY_ADDED=${DOT_LOCAL_ALREADY_ADDED}\n\
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"

Просмотреть файл

@ -6,16 +6,16 @@
# Syntax: ./common-redhat.sh <install zsh flag> <username> <user UID> <user GID>
set -e
INSTALL_ZSH=${1:-"true"}
USERNAME=${2:-"$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)"}
USER_UID=${3:-1000}
USER_GID=${4:-1000}
UPGRADE_PACKAGES=${5:-true}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" before running the script.'
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
@ -77,7 +77,7 @@ chown $USER_UID:$USER_GID /home/$USERNAME/.bashrc
# Optionally install and configure zsh
if [ "$INSTALL_ZSH" = "true" ] && [ ! -d "/root/.oh-my-zsh" ]; then
yum install -y zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
curl -fsSLo- https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh | bash 2>&1
echo "export PATH=\$PATH:\$HOME/.local/bin" >> /root/.zshrc
cp -R /root/.oh-my-zsh /home/$USERNAME
cp /root/.zshrc /home/$USERNAME

Просмотреть файл

@ -6,6 +6,22 @@
# Syntax: ./docker-debian.sh <enable non-root docker socket access flag> <source socket> <target socket> <non-root user>
ENABLE_NONROOT_DOCKER=${1:-"true"}
SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"}
TARGET_SOCKET=${3:-"/var/run/docker.sock"}
USERNAME=${4:-"vscode"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Function to run apt-get if needed
apt-get-update-if-needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
@ -16,23 +32,10 @@ apt-get-update-if-needed()
fi
}
set -e
ENABLE_NONROOT_DOCKER=${1:-"true"}
SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"}
TARGET_SOCKET=${3:-"/var/run/docker.sock"}
NONROOT_USER=${4:-"vscode"}
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" in your Dockerfile before running the script.'
exit 1
fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install Docker CLI if not already installed
if ! type docker > /dev/null 2>&1; then
if type docker > /dev/null 2>&1; then
echo "Docker CLI already installed."
else
if ! type curl > /dev/null 2>&1; then
apt-get-update-if-needed
apt-get -y install --no-install-recommends apt-transport-https ca-certificates curl gnupg2 lsb-release
@ -41,32 +44,41 @@ if ! type docker > /dev/null 2>&1; then
echo "deb [arch=amd64] https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]') $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get -y install --no-install-recommends docker-ce-cli
else
echo "Docker CLI already installed."
fi
# Install Docker Compose if not already installed
if ! type docker-compose > /dev/null 2>&1; then
if type docker-compose > /dev/null 2>&1; then
echo "Docker Compose already installed."
else
LATEST_COMPOSE_VERSION=$(curl -sSL "https://api.github.com/repos/docker/compose/releases/latest" | grep -o -P '(?<="tag_name": ").+(?=")')
curl -sSL "https://github.com/docker/compose/releases/download/${LATEST_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
else
echo "Docker Compose already installed."
fi
if [ ! -f "/usr/local/share/docker-init.sh" ]; then
# By default, make the source and target sockets the same
if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then
touch "${SOURCE_SOCKET}"
ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}"
chown -h "${NONROOT_USER}" "${TARGET_SOCKET}"
fi
# If init file already exists, exit
if [ -f "/usr/local/share/docker-init.sh" ]; then
exit 0
fi
# If enabling non-root access and specified user is found, setup socat and add script
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && id -u ${NONROOT_USER} > /dev/null 2>&1; then
apt-get-update-if-needed
apt-get -y install socat
tee /usr/local/share/docker-init.sh << EOF
# By default, make the source and target sockets the same
if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then
touch "${SOURCE_SOCKET}"
ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}"
fi
# Add a stub if not adding non-root user access, user is root, or the specified user does not exist
if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
echo '/usr/bin/env bash -c "\$@"' > /usr/local/share/docker-init.sh
chmod +x /usr/local/share/docker-init.sh
exit 0
fi
# If enabling non-root access and specified user is found, setup socat and add script
chown -h "${USERNAME}":root "${TARGET_SOCKET}"
apt-get-update-if-needed
apt-get -y install socat
tee /usr/local/share/docker-init.sh > /dev/null \
<< EOF
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
@ -96,12 +108,12 @@ log()
}
echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null
log "Ensuring ${NONROOT_USER} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}"
log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}"
# If enabled, try to add a docker group with the right GID. If the group is root,
# fall back on using socat to forward the docker socket to another unix socket so
# that we can set permissions on it without affecting the host.
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${NONROOT_USER}" != "root" ] && [ "${NONROOT_USER}" != "0" ]; then
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then
SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET})
if [ "\${SOCKET_GID}" != "0" ]; then
log "Adding user to group with GID \${SOCKET_GID}."
@ -109,8 +121,8 @@ if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_
sudoIf groupadd --gid \${SOCKET_GID} docker-host
fi
# Add user to group if not already in it
if [ "\$(id ${NONROOT_USER} | grep -E 'groups=.+\${SOCKET_GID}\(')" = "" ]; then
sudoIf usermod -aG \${SOCKET_GID} ${NONROOT_USER}
if [ "\$(id ${USERNAME} | grep -E 'groups=.+\${SOCKET_GID}\(')" = "" ]; then
sudoIf usermod -aG \${SOCKET_GID} ${USERNAME}
fi
else
# Enable proxy if not already running
@ -118,7 +130,7 @@ if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_
log "Enabling socket proxy."
log "Proxying ${SOURCE_SOCKET} to ${TARGET_SOCKET} for vscode"
sudoIf rm -rf ${TARGET_SOCKET}
(sudoIf socat UNIX-LISTEN:${TARGET_SOCKET},fork,mode=660,user=${NONROOT_USER} UNIX-CONNECT:${SOURCE_SOCKET} 2>&1 | sudoIf tee -a \${SOCAT_LOG} > /dev/null & echo "\$!" | sudoIf tee \${SOCAT_PID} > /dev/null)
(sudoIf socat UNIX-LISTEN:${TARGET_SOCKET},fork,mode=660,user=${USERNAME} UNIX-CONNECT:${SOURCE_SOCKET} 2>&1 | sudoIf tee -a \${SOCAT_LOG} > /dev/null & echo "\$!" | sudoIf tee \${SOCAT_PID} > /dev/null)
else
log "Socket proxy already running."
fi
@ -131,8 +143,5 @@ fi
set +e
"\$@"
EOF
else
echo '/usr/bin/env bash -c "\$@"' > /usr/local/share/docker-init.sh
fi
chmod +x /usr/local/share/docker-init.sh
fi
chmod +x /usr/local/share/docker-init.sh
chown ${USERNAME}:root /usr/local/share/docker-init.sh

Просмотреть файл

@ -1,15 +1,15 @@
#!/usr/bin/env bash
# Syntax: ./docker-redhat.sh <enable non-root docker socket access flag> <source socket> <target socket> <non-root user>
set -e
ENABLE_NONROOT_DOCKER=${1:-"true"}
SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"}
TARGET_SOCKET=${3:-"/var/run/docker.sock"}
NONROOT_USER=${4:-"vscode"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" before running the script.'
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
@ -67,7 +67,8 @@ fi
# If enabling non-root access, setup socat
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ]; then
yum -y install socat
tee /usr/local/share/docker-init.sh << EOF
tee /usr/local/share/docker-init.sh \
<< EOF
#!/usr/bin/env bash
set -e

Просмотреть файл

@ -0,0 +1,70 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
# Syntax: ./gradle-debian.sh <gradle version> [gradle home] [non-root-user] [gradle SHA 256]
GRADLE_VERSION=$1
GRADLE_HOME=${2:-"/usr/local/share/gradle"}
USERNAME=${3:-"vscode"}
GRADLE_DOWNLOAD_SHA=${4:-"no-check"}
set -e
if [ -d "${GRADLE_HOME}" ]; then
echo "Gradle already installed."
exit 0
fi
if [ -z "$1" ]; then
echo -e "Required argument missing.\n\ngradle-debian.sh <gradle version> [gradle home] [non-root-user] [gradle SHA 256]"
exit 1
fi
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Treat a user name of "none" or non-existant user as root
if [ "${USERNAME}" = "none" ] && ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
# Install curl, apt-get dependencies if missing
if ! type curl > /dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
apt-get update
fi
apt-get -y install --no-install-recommends ca-certificates curl gnupg2
fi
# Function to su if user exists and is not root
suIf() {
if [ "${USERNAME}" != "root" ]; then
su ${USERNAME} -c "$@"
else
"$@"
fi
}
# Install Gradle
echo "Downloading Gradle..."
suIf "$(cat \
<< EOF
mkdir -p /tmp/downloads
curl -sSL --output /tmp/downloads/archive-gradle.zip https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip
([ "${GRADLE_DOWNLOAD_SHA}" = "no-check" ] || echo "${GRADLE_DOWNLOAD_SHA} */tmp/downloads/archive-gradle.zip" | sha256sum --check - )
unzip -q /tmp/downloads/archive-gradle.zip -d /tmp/downloads/
EOF
)"
mv -f /tmp/downloads/gradle* ${GRADLE_HOME}
chown ${USERNAME}:root ${GRADLE_HOME}
ln -s ${GRADLE_HOME}/bin/gradle /usr/local/bin/gradle
rm -rf /tmp/downloads
echo "Done."

Просмотреть файл

@ -0,0 +1,75 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
# Syntax: ./maven-debian.sh <maven version> [maven home] [non-root user] [maven SHA 512]
MAVEN_VERSION=$1
MAVEN_HOME=${2:-"/usr/local/share/maven"}
USERNAME=${3:-"vscode"}
MAVEN_DOWNLOAD_SHA=${4:-"no-check"}
set -e
if [ -d "${MAVEN_HOME}" ]; then
echo "Maven already installed."
exit 0
fi
if [ -z "$1" ]; then
echo -e "Required argument missing.\n\nmaven-debian.sh <maven version> [maven home] [non-root user] [maven SHA 512]"
exit 1
fi
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Treat a user name of "none" or non-existant user as root
if [ "${USERNAME}" = "none" ] && ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
# Install curl, apt-get dependencies if missing
if ! type curl > /dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
apt-get update
fi
apt-get -y install --no-install-recommends ca-certificates curl gnupg2
fi
# Function to su if user exists and is not root
suIf() {
if [ "${USERNAME}" != "root" ]; then
su ${USERNAME} -c "$@"
else
"$@"
fi
}
# Creat folder, add maven settings
mkdir -p ${MAVEN_HOME} ${MAVEN_HOME}/ref
tee ${MAVEN_HOME}/ref/maven-settings.xml > /dev/null \
<< EOF
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>${MAVEN_HOME}/ref/repository</localRepository>
</settings>
EOF
chown -R ${USERNAME}:root ${MAVEN_HOME}
# Install Maven
echo "Downloading Maven..."
suIf "$(cat \
<< EOF
curl -fsSL -o /tmp/maven.tar.gz https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz
([ "${MAVEN_DOWNLOAD_SHA}" = "dev-mode" ] || echo "${MAVEN_DOWNLOAD_SHA} */tmp/maven.tar.gz" | sha512sum -c - )
tar -xzf /tmp/maven.tar.gz -C ${MAVEN_HOME} --strip-components=1
rm -f /tmp/maven.tar.gz
EOF
)"
ln -s ${MAVEN_HOME}/bin/mvn /usr/local/bin/mvn
echo "Done."

Просмотреть файл

@ -6,24 +6,20 @@
# Syntax: ./node-debian.sh <directory to install nvm> <node version to install (use "none" to skip)> <non-root user>
set -e
export NVM_DIR=${1:-"/usr/local/share/nvm"}
export NODE_VERSION=${2:-"lts/*"}
NONROOT_USER=${3:-"vscode"}
USERNAME=${3:-"vscode"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo 'Script must be run a root. Use sudo or set "USER root" before running the script.'
echo -e 'Script must be run a root. Use sudo, su, or add "USER root" to\nyour Dockerfile before running this script.'
exit 1
fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
if [ "${NODE_VERSION}" = "none" ]; then
export NODE_VERSION=
fi
# Install curl, apt-get dependencies if missing
if ! type curl > /dev/null 2>&1; then
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
@ -32,43 +28,76 @@ if ! type curl > /dev/null 2>&1; then
apt-get -y install --no-install-recommends apt-transport-https ca-certificates curl gnupg2
fi
# Install NVM
if [ ! -d "${NVM_DIR}" ]; then
mkdir -p ${NVM_DIR}
curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash 2>&1
if [ "${NODE_VERSION}" != "" ]; then
/bin/bash -c "source $NVM_DIR/nvm.sh && nvm alias default ${NODE_VERSION}" 2>&1
fi
if id -u $NONROOT_USER > /dev/null 2>&1; then
echo -e "export NVM_DIR=\"${NVM_DIR}\"\n\
[ -s \"\$NVM_DIR/nvm.sh\" ] && \\. \"\$NVM_DIR/nvm.sh\"\n\
[ -s \"\$NVM_DIR/bash_completion\" ] && \\. \"\$NVM_DIR/bash_completion\"" \
| tee -a /home/${NONROOT_USER}/.bashrc /home/${NONROOT_USER}/.zshrc >> /root/.zshrc
echo -e "if [ \"\$(stat -c '%U' \$NVM_DIR)\" != \"${NONROOT_USER}\" ]; then\n\
sudo chown -R ${NONROOT_USER}:root \$NVM_DIR\n\
fi" | tee -a /root/.bashrc /root/.zshrc /home/${NONROOT_USER}/.bashrc >> /home/${NONROOT_USER}/.zshrc
chown ${NONROOT_USER}:${NONROOT_USER} /home/${NONROOT_USER}/.bashrc /home/${NONROOT_USER}/.zshrc
chown -R ${NONROOT_USER}:root ${NVM_DIR}
else
echo "Non-root user ${NONROOT_USER} not found. Skipping setup for this user."
fi
else
echo "NVM already installed."
if [ "${NODE_VERSION}" != "" ]; then
nvm install "${NODE_VERSION}"
fi
# Treat a user name of "none" as root
if [ "${USERNAME}" = "none" ]; then
USERNAME=root
fi
if [ "${NODE_VERSION}" = "none" ]; then
export NODE_VERSION=
fi
# Install yarn
if ! type yarn > /dev/null 2>&1; then
if type yarn > /dev/null 2>&1; then
echo "Yarn already installed."
else
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - 2>/dev/null
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt-get update
apt-get -y install --no-install-recommends yarn
else
echo "Yarn already installed."
fi
# Install the specified node version if NVM directory already exists, then exit
if [ -d "${NVM_DIR}" ]; then
echo "NVM already installed."
if [ "${NODE_VERSION}" != "" ]; then
suIf "nvm install ${NODE_VERSION}"
fi
exit 0
fi
mkdir -p ${NVM_DIR}
# Set up non-root user if applicable
if [ "${USERNAME}" != "root" ] && id -u $USERNAME > /dev/null 2>&1; then
# Add NVM init to non-root user
tee -a /home/${USERNAME}/.bashrc /home/${USERNAME}/.zshrc >> /root/.zshrc \
<< EOF
export NVM_DIR="${NVM_DIR}"
[ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh"
[ -s "\$NVM_DIR/bash_completion" ] && . "\$NVM_DIR/bash_completion"
EOF
# Add code to update NVM ownership if UID/GID changes
tee -a /root/.bashrc /root/.zshrc /home/${USERNAME}/.bashrc >> /home/${USERNAME}/.zshrc \
<<EOF
if [ "\$(stat -c '%U' \$NVM_DIR)" != "${USERNAME}" ]; then
sudo chown -R ${USERNAME}:root \$NVM_DIR
fi
EOF
# Update ownership
chown ${USERNAME} ${NVM_DIR} /home/${USERNAME}/.bashrc /home/${USERNAME}/.zshrc
fi
# Function to su if user exists and is not root
suIf() {
if [ "${USERNAME}" != "root" ] && id -u ${USERNAME} > /dev/null 2>&1; then
su ${USERNAME} -c "$@"
else
"$@"
fi
}
# Run NVM installer as non-root if needed
suIf "$(cat \
<< EOF
curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
if [ "${NODE_VERSION}" != "" ]; then
source $NVM_DIR/nvm.sh
nvm alias default ${NODE_VERSION}
fi
EOF
)" 2>&1

Просмотреть файл

@ -3,36 +3,18 @@
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
# Test defaults
ARG IMAGE_TO_TEST=debian:10
FROM ${IMAGE_TO_TEST}
ARG DISTRO="debian"
ARG USERNAME="vscode"
ARG INSTALL_DOCKER="true"
ARG UPGRADE_PACKAGES="true"
COPY *.sh /tmp/
COPY test/*.sh /tmp
RUN chmod +x /tmp/*.sh
# Run common script
RUN /tmp/common-${DISTRO}.sh true ${USERNAME} 1000 1000 ${UPGRADE_PACKAGES}
ARG DISTRO="debian"
ARG USE_DEFAULTS="true"
ARG USERNAME="vscode"
RUN /tmp/run-scripts.sh /tmp ${DISTRO} ${USE_DEFAULTS} ${USERNAME} false false 10
RUN if [ "${DISTRO}" != "alpine" ]; then\
# Run Docker script
/tmp/docker-${DISTRO}.sh true /var/run/docker-host.sock /var/run/docker.sock ${USERNAME}; \
else \
echo -e '#!/bin/bash\n"$@"' | tee /usr/local/share/docker-init.sh \
&& chown ${USERNAME} /usr/local/share/docker-init.sh \
&& chmod +x /usr/local/share/docker-init.sh; \
fi
RUN if [ "${DISTRO}" = "debian" ]; then \
# Run Node script
/tmp/node-${DISTRO}.sh "/usr/local/share/nvm" 12 ${USERNAME}; \
fi
# Setting the ENTRYPOINT to docker-init.sh will configure non-root access to
# the Docker socket if "overrideCommand": false is set in devcontainer.json.
# The script will also execute CMD if you need to alter startup behaviors.
ENTRYPOINT [ "/usr/local/share/docker-init.sh" ]
CMD [ "sleep", "infinity" ]

Просмотреть файл

@ -1,5 +1,5 @@
{
"name": "Script Tester",
"name": "Script Tester - Alpine",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",

Просмотреть файл

@ -1,16 +1,18 @@
{
"name": "Script Tester",
"name": "Script Tester - Debian",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",
"args": {
"IMAGE_TO_TEST": "debian:10",
"USERNAME": "vscode",
"DISTRO": "debian"
"DISTRO": "debian",
"USERNAME": "tester",
"USE_DEFAULTS": "false"
}
},
"remoteUser": "tester",
"mounts": [ "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" ],
"overrideCommand": false,
"overrideCommand": true,
"settings": {
"terminal.integrated.shell.linux": null
@ -18,7 +20,5 @@
"extensions": [
"ms-azuretools.vscode-docker"
],
"remoteUser": "vscode"
]
}

Просмотреть файл

@ -1,5 +1,5 @@
{
"name": "Script Tester",
"name": "Script Tester - RedHat",
"build": {
"dockerfile": "../Dockerfile",
"context": "../../",

Просмотреть файл

@ -0,0 +1,46 @@
#!/bin/sh
SCRIPT_DIR=${1-"/tmp"}
DISTRO=${2:-debian}
USE_DEFAULTS=${3:-true}
USERNAME=${4:-vscode}
UPGRADE_PAGKES=${5:-true}
ENABLE_NONROOT=${6:-true}
NODE_VERSION=${7:-"lts/*"}
MAVEN_VERSION=${8:-"3.6.3"}
MAVEN_DOWNLOAD_SHA=${9:-"c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0"}
GRADLE_VERSION=${10:-"5.4.1"}
GRADLE_DOWNLOAD_SHA=${11:-"7bdbad1e4f54f13c8a78abc00c26d44dd8709d4aedb704d913fb1bb78ac025dc"}
runScript()
{
SCRIPT=$1
ARGS=$2
REQUIRED_PREFIX_ARGS=${3:-""}
echo "**** Testing $SCRIPT ****"
if [ "${USE_DEFAULTS}" = "true" ]; then
echo "Using defaults..."
${SCRIPT} ${REQUIRED_PREFIX_ARGS}
else
echo "Arguments: ${REQUIRED_PREFIX_ARGS} ${ARGS}"
${SCRIPT} ${REQUIRED_PREFIX_ARGS} ${ARGS}
fi
echo "**** Done! ****\n"
}
runScript ${SCRIPT_DIR}/common-${DISTRO}.sh "true ${USERNAME} 1000 1000 ${UPGRADE_PACKAGES}"
if [ "${DISTRO}" = "debian" ]; then
runScript ${SCRIPT_DIR}/node-${DISTRO}.sh "/usr/local/share/nvm ${NODE_VERSION} ${USERNAME}"
runScript ${SCRIPT_DIR}/maven-${DISTRO}.sh "/usr/local/share/maven ${USERNAME} ${MAVEN_DOWNLOAD_SHA}" "${MAVEN_VERSION}"
runScript ${SCRIPT_DIR}/gradle-${DISTRO}.sh "/usr/local/share/gradle ${USERNAME} ${GRADLE_DOWNLOAD_SHA}" "${GRADLE_VERSION}"
fi
# Run Docker script
if [ "${DISTRO}" != "alpine" ]; then
runScript /tmp/docker-${DISTRO}.sh "true /var/run/docker-host.sock /var/run/docker.sock ${USERNAME}"
else
echo '#!/bin/bash\n"$@"' | tee /usr/local/share/docker-init.sh
chown ${USERNAME} /usr/local/share/docker-init.sh
chmod +x /usr/local/share/docker-init.sh
fi