diff --git a/docker-local-environment/Dockerfile b/docker-local-environment/Dockerfile new file mode 100644 index 000000000000..04fe284e7aee --- /dev/null +++ b/docker-local-environment/Dockerfile @@ -0,0 +1,61 @@ +# The base image +FROM ubuntu:20.04 + +# Prevent interactive prompts during installation +ENV DEBIAN_FRONTEND=noninteractive + +# Initialize system tools +RUN apt-get update && apt-get install -y \ + iputils-ping \ + wget \ + gnupg \ + openjdk-17-jdk \ + maven \ + python3 \ + python3-pip \ + mysql-server \ + mysql-client \ + git \ + curl \ + libssl-dev \ + build-essential \ + net-tools \ + sudo \ + lsof \ + iproute2 \ + tar + +# Set JAVA_HOME globally +ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-arm64 +ENV PATH="$JAVA_HOME/bin:$PATH" + +# Verify Java installation +RUN java -version && echo $JAVA_HOME + +# Download & Extract CloudStack Source Code +RUN mkdir -p /cloudstack && \ + wget https://dlcdn.apache.org/cloudstack/releases/4.20.0.0/apache-cloudstack-4.20.0.0-src.tar.bz2 -P /tmp && \ + tar -xjf /tmp/apache-cloudstack-4.20.0.0-src.tar.bz2 -C /cloudstack + +# Set working directory +WORKDIR /cloudstack/apache-cloudstack-4.20.0.0-src + +# Build from source +RUN mvn clean install -P developer,systemvm + +# Ensure MySQL user has a valid shell before installation +RUN usermod -s /bin/bash mysql + +# Create a MySQL data directory volume +VOLUME /var/lib/mysql + +# Copy entrypoint and init scripts into CloudStack directory +COPY docker-entrypoint.sh /cloudstack/docker-entrypoint.sh +COPY init-mysql.sh /cloudstack/init-mysql.sh +RUN chmod +x /cloudstack/docker-entrypoint.sh /cloudstack/init-mysql.sh + +# Expose CloudStack and MySQL ports +EXPOSE 8080 3306 + +# Keep the container running for debugging +CMD ["tail", "-f", "/dev/null"] diff --git a/docker-local-environment/docker-compose.yml b/docker-local-environment/docker-compose.yml new file mode 100644 index 000000000000..a124bae613f7 --- /dev/null +++ b/docker-local-environment/docker-compose.yml @@ -0,0 +1,52 @@ +services: + mysql: + image: mysql:8.0 + restart: always + networks: + cloudstack-docker_mynetwork: + aliases: + - mysql + environment: + MYSQL_ROOT_PASSWORD: rootpass + MYSQL_DATABASE: cloud + MYSQL_USER: cloud + MYSQL_PASSWORD: cloud + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + command: [ + "--default-authentication-plugin=mysql_native_password", + "--bind-address=0.0.0.0" + ] + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 5s + timeout: 3s + retries: 5 + + cloudstack: + build: . + restart: no + depends_on: + mysql: + condition: service_healthy + environment: + DB_HOST: mysql + DB_USER: cloud + DB_PASSWORD: cloud + volumes: + - ./docker-entrypoint.sh:/cloudstack/docker-entrypoint.sh + - ./init-mysql.sh:/cloudstack/init-mysql.sh + command: "/bin/bash /cloudstack/docker-entrypoint.sh" + networks: + cloudstack-docker_mynetwork: + aliases: + - cloudstack + +volumes: + mysql_data: + +networks: + cloudstack-docker_mynetwork: + driver: bridge diff --git a/docker-local-environment/docker-entrypoint.sh b/docker-local-environment/docker-entrypoint.sh new file mode 100644 index 000000000000..d56306297cdc --- /dev/null +++ b/docker-local-environment/docker-entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e # Exit immediately on error + +echo "----Starting MySQL container..." + +# Start MySQL in the background +service mysql start + +# Wait for MySQL to fully initialize +until mysqladmin ping &>/dev/null; do + echo "Waiting for MySQL to be ready..." + sleep 2 +done + +echo "----MySQL is running!" + +# Run the initialization script for database setup +bash /cloudstack/init-mysql.sh + +echo "----Starting CloudStack Management Server..." +service cloudstack-management start + +# Keep the container running +exec bash +tail -f /dev/null diff --git a/docker-local-environment/init-mysql.sh b/docker-local-environment/init-mysql.sh new file mode 100644 index 000000000000..96f87dd972af --- /dev/null +++ b/docker-local-environment/init-mysql.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e # Exit immediately on error + +echo "----Running MySQL initialization script..." + +# Wait until MySQL is ready, pings the MySQL server awaiting a response +until mysqladmin ping &>/dev/null; do + echo "----Waiting for MySQL to be ready..." + sleep 2 +done + +# Validate the database exists before creating it +DB_EXISTS=$(mysql -u root -p${MYSQL_ROOT_PASSWORD} -se "SHOW DATABASES LIKE 'cloud';") + +if [ -z "$DB_EXISTS" ]; then + echo "----Creating MySQL database..." + mysql -u root -p${MYSQL_ROOT_PASSWORD} -e "CREATE DATABASE cloud;" +else + echo "----Database 'cloud' already exists—skipping creation." +fi + +# Validate the cloud user exists before creating it +USER_EXISTS=$(mysql -u root -p${MYSQL_ROOT_PASSWORD} -se "SELECT COUNT(*) FROM mysql.user WHERE user='cloud';") + +if [ "$USER_EXISTS" -eq 0 ]; then + echo "----Creating MySQL user..." + mysql -u root -p${MYSQL_ROOT_PASSWORD} -e " + CREATE USER 'cloud'@'%' IDENTIFIED BY 'cloud'; + GRANT ALL PRIVILEGES ON cloud.* TO 'cloud'@'%'; + FLUSH PRIVILEGES;" +else + echo "----MySQL user 'cloud' already exists—skipping." +fi + +echo "----MySQL setup complete"