OSXIEC is a native docker-like solution for macOS developed by Okerew. It leverages native macOS features to provide containerization capabilities, albeit with some limitations compared to Docker.
![Watch the video](https://private-user-images.githubusercontent.com/93822247/348261341-d45e77d8-9532-482f-b4f6-874a301f4916.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQyNjc3NjgsIm5iZiI6MTcyNDI2NzQ2OCwicGF0aCI6Ii85MzgyMjI0Ny8zNDgyNjEzNDEtZDQ1ZTc3ZDgtOTUzMi00ODJmLWI0ZjYtODc0YTMwMWY0OTE2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODIxVDE5MTEwOFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRlZTk4NGUxZWEyMmY4Y2RjMjI3MDdmMmNlY2EwMjdmOTc1NDljMzk2NDliYzcwZmZmNzQxMzVmMDgwY2EzY2UmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.IxqaSZQ1EWqjfprgVI7d55UOy-ybwQUjAwFmKEdrmZI)
HomeBrew for installing dependencies
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Curl
brew install curl
Readline
brew install readline
Json-c
brew install [email protected]
Ninja for building
brew install ninja
Cmake for building
brew install cmake
Xcode https://apps.apple.com/us/app/xcode/id497799835?mt=12
-
Download the Release: Download the
osxiec_cli.tar.gz
andosxiec_gui.tar.gz
if you want a gui app file from the releases section. -
Extract the Archive:
tar -xvzf osxiec_cli.tar.gz
For gui version
tar -xvzf osxiec_gui.tar.gz
-
Run installation script in the extracted cli directory:
sudo sh install.sh
-
If downloaded osxiec_gui
Copy app bundle from osxiec_gui.tar.gz to /Applications then run the app bundle or run osxiec.jar
To update to a new release, repeat steps 1, 2, and 3 if using osxiec_gui also step 4.
Containerize a Directory: containerizes a directory
sudo osxiec -contain {directory_path} {some_name}.bin {path_to_config_file_in_directory_path} {container_config_file}
Execute a Container: executes container
sudo osxiec -execute {some_name}.bin
Execute with Port Argument: execute with port
sudo osxiec -execute {some_name} -port {PORT_NUMBER}
Create a cluster ( virtualized network ) create a cluster
sudo osxiec -network create {network_name} {vlan_id}
Remove a vlan network removes a vlan network
sudo osxiec -network remove {network_name} {vlan_id}
Run with vlan config run with vlan config
sudo osxiec -run {some_name} {network_name} -port {PORT_NUMBER}
Version checks the current version
osxiec --version
Pull pulls an image from osxiec hub
osxiec -pull {container_name}
Search searches osxiec hub
osxiec -search {search_term_for_osxiec_hub}
Upload allows to upload a file to osxiec hub
osxiec -upload {filename} {username} {password} {description}
Convert to Docker converts to docker
osxiec -convert-to-docker {bin_file} {output_directory} {base_image} [custom_dockerfile]
Clean this will clean the container volume images from /tmp
sudo osxiec -clean
Detach detaches the container images
osxiec -detach
Help shows all the commands
osxiec -help
Deploy deploys a container
sudo osxiec -deploy {path_to_config} -port {PORT_NUMBER}
Scan scans a container for security vulnerabilities
osxiec -scan {some_name.bin}
Deploym deploys multiple containers, this is a work in progress, for now it works mostly fine with start config
sudo osxiec -deploym {config_file}
Oexec executes a container in offline mode without any networking or usage of ports
sudo osxiec -oexec {bin_file_path}
Extract extracts files and folders from a container
sudo osxiec -extract {bin_file_path}
Convert to oci converts to an oci container
osxiec -convert-to-oci {bin_file_path} {output_path} {arch} {author}
Craft crafts a container from a directory and a bin input file
sudo osxiec -craft {directory_path} {bin_input_file} {output_file} {start_config_file} {container_config_file}
Make sure to include any dependencies or executables you can obtain these by searching for where a dependency or executable is located and copying it along with it's dependencies.
Example structure
[
"container_name",
{
"some_content",
"subfolder1" [
executable1
"some_content"
]
"start_config_file"
"some_executable"
"dependency"
}
]
Script Example: For example if you have a node project make sure to include somewhere the node executable in the directory you want to contain, then run the script with the node executable.
console.log("Hello World")
Do path/to/node_executable_in_container/ script.js
Containing
To contain a directory run the osxiec -contain {directory_path} {container_name} {start_config_file}
This will also scan the container for security vulnerabilities.
After creating a container or downloading one. You can execute one with
osxiec -execute {container_name}
If you want you can also use a custom port with -port {PORT_NUMBER}
Run with vlan
If you have created a vlan network like said in the next point you can run the container with
osxiec -run {container_name} {network_name}
You can also add the port argument with -port {PORT_NUMBER}
When executing
Normally it will start a listener which will allow it to communicate with other containers.
If you want to access the container terminal just press enter.
- help shows all the commands
- debug debugs the container
- scale scales the resources of the container
- osxs Execute an osxs script file
- xs Execute an osxs script command
- autoscale automatically scales the resources of the container
- status shows the status of the container
To create a network you can run osxiec -network create {network_name} {vlan_id}
The network_name can be any string like "test" for example.
The vlan id can be any number from 1-4094.
For example osxiec -network create test 6
Create docker file
# Test Dockerfile for osxiec to Docker conversion
# Use a lightweight base image
FROM alpine:latest
# Set the working directory in the container
WORKDIR /app
# Copy the application files from the osxiec container
# Note: This will be handled by the conversion script, so we don't need COPY instructions here
# Install any needed packages
RUN apk add --no-cache python3 py3-pip
# Set environment variables (these will be overwritten by the conversion script if not using a custom Dockerfile)
ENV MEMORY_SOFT_LIMIT=256m
ENV MEMORY_HARD_LIMIT=512m
ENV CPU_PRIORITY=20
# Make port 8080 available to the world outside this container
EXPOSE 8080
# Run a simple Python HTTP server when the container launches
CMD ["python3", "-m", "http.server", "8080"]
Run convert-to-docker
For this example
osxiec -convert-to-docker {container_name} {output_directory} alpine:latest samples/dockerfile
Create a config file
source_dir=/path/to/source/directory
container_file=/path/to/output/container.bin
network_name=my_network
start_config=/path/to/start_config.sh
Deploy
sudo osxiec -deploy {path_to_config_file}
You can also use -port {PORT_NUMBER}
Deploym you can also deploy multiple containers, this is a work in progress though.
sudo osxiec -deploym {config_file} {PORT_NUMBER1} {PORT_NUMBER2} etc.
Config
path_to_container1_config {network_name}
path_to_container2_config {network_name}
Osxiec script is a scripting language created for managing osxiec containers.
Set Memory
SET_MEMORY {memory_soft} {memory_hard}
Set CPU Priority
SET_CPU {cpu_priority}
Execute
EXECUTE {command}
Conditional Execution
IF {condition} EXECUTE {command}
Sleep
SLEEP {seconds}
Log
LOG {message}
Execute File
EXECUTE_FILE {path_to_script}
Set Variable
SET {variable} {value}
While Loop
WHILE {condition} {commands} END
For Loop
FOR {variable} TO {2variable} STEP {value} {commands} END
ELSE
IF {condition} ELSE {commands} END
Note ELSE statement for now doesn't work with LOG and is a work in progress
Example
# This is an example script for the OSXIEC scripting language
SET counter 0
SET limit 10
# Loop from 0 to 10
FOR counter=0 TO limit STEP 2
IF counter==5
LOG "Counter is 5"
END
SLEEP 1
END
IF $var==5 LOG Variable is 5 ELSE LOG Variable is not 5
# Loop while counter is less than limit
WHILE counter<limit
IF counter==5
LOG "Counter is 5"
END
SET counter $(($counter + 1))
SLEEP 1
END
# Log the start of the script
LOG Starting script for $container_name
# Set container memory limits
SET_MEMORY $mem_soft $mem_hard
# Set CPU priority
SET_CPU $cpu_priority
# Execute a command
EXECUTE echo "Container $container_name initialized"
# Conditional execution
SET status running
IF status==running EXECUTE echo "Container is operational"
# Sleep for 2 seconds
SLEEP 2
# Echo some information
ECHO Container $container_name is configured with:
ECHO - Memory limits: $mem_soft MB (soft) / $mem_hard MB (hard)
ECHO - CPU priority: $cpu_priority
When in a container, you can use the following commands to debug the container.
To start debugging debug
Then you can use these commands
step
which steps to the next command
break <command>
Creates a breakpoint at the specified command
print <var>
Prints the value of the specified variable of the container
print
Prints the whole container state
help
Shows what you can do
continue
Continues execution of the container
This is a place where you can upload your containers to.
This is the source code for the gui version of osxiec.
A terminal emulator specifically created for osxiec
Git clone the repository
git clone https://github.com/Okerew/osxiec.git
Go to the directory
cd osxiec
Build the osxiec executable
mkdir {build-directory}
cd {build-directory}
cmake -S .. -B . -G "Ninja"
ninja
Give permissions to scripts if needed
sudo chmod +x scripts/osxiec_deploy_multiple.sh
sudo chmod +x scripts/install.sh
Finalize to make it work put all executables in a one folder, copy there install.sh and run it
Git clone the gui
git clone https://github.com/Okerew/osxiec_gui.git
Go to the directory
cd osxiec_gui
Build the class
javac OsxiecApp.java
Build the jar
jar -cvfe osxiec.jar OsxiecApp OsxiecApp.class
Copy jar into app bundle, remove the previous one
cp osxiec.jar osxiec.app/Contents/Resources
If using the one from release, delete the previous one
Copy the icon into Contents/Resources
Finally, copy the run_app_bundle.sh into the bundle as osxiec_gui
cp run_app_bundle.sh osxiec.app/Contents/MacOS/osxiec_gui
Example plugin can be seen in samples/sample_plugin.c, this should make you understand how osxiec loads plugins.
Build plugin
gcc -shared -fPIC -o {plugin_name}.so {plugin_name}.c
Install plugin
sudo cp {plugin_name}.so ~/.osxiec/plugins
After this on the execution of osxiec command the plugin will be loaded.
- Not a Docker Replacement: While OSXIEC offers similar functionality to Docker, it lacks some advanced features of Docker. It is more supposed to be a quicker testing tool than docker on macOS, it is not designed to replace it, just to test basic ideas and software, distribute macOS software.
- macOS Only: OSXIEC uses native macOS features and is not compatible with other operating systems.
- Isolation Limitations: Due to macOS limitations, complete isolation like in Linux is not possible. The contained directory will have some access to the outside environment, you can have a start config file if needed.
- Supported Features: Despite its limitations, OSXIEC provides isolation using namespaces, setuid, image layers, basic user process control, memory and CPU control, and special permissions using user IDs and group IDs, unpacking the image into a disk image(APFS), vlans.
- Support: Remember that not everything will work fully for example node won't work fully because it is making sys calls which spawn things outside the container, in this example local things that do not rely on the repl server will work.
- Temps: If you need a lot of storage for the moment, and you used a container use the clean command.
- Why is chroot not used? Chroot requires for SIP to be disabled, which causes many security risks, chroot can be easily exited by any process, using the normal macOS restrictions is way more secure, reliable, having it disabled causes many permission issues.
- Sandbox deprecation error yes I know that sandbox innit is deprecated but there isn't really an alternative for it unless I would use xcode and there is no way I am using it to rebuild this.