I want to redeploy a docker container via Jenkinsfile on a remote EC2, but I struggle to find a solution that works with ssh. I want to have to lookup if the container already exist and remove it first.
What I tried: I wrote a script which works on my local machine but there is no need for ssh.
This is the working stage from my Jenkinsfile.
stage('Deploy Docker container on HOST') {
steps {
script {
// Check if container exists
def containerId = sh(script: "docker ps --quiet --filter name=$CONTAINER_NAME", returnStdout: true).trim()
if (containerId.isEmpty()) {
echo "Container $CONTAINER_NAME not found. Skipping stop/remove steps."
} else {
echo "Stopping and removing existing container $CONTAINER_NAME ..."
sh "docker stop $CONTAINER_NAME"
sh "docker rm $CONTAINER_NAME"
sh "docker rmi $DOCKERH_REPO/$IMAGE_TAG:latest" // Remove leftover image if needed
sh "docker rmi $DOCKERH_REPO/$IMAGE_TAG:$BUILD_VERSION" // Remove leftover image if needed
}
// Always run the container regardless of previous existence
echo "Starting container $CONTAINER_NAME ..."
sh "$DOCKER_RUN"
sh "docker image prune --force"
}
}
}
Now I would like to be able to do the same but on a remote server via SSH. I moved the cript to an external groovy for this stage to be more clean.
Stage
stage('Deploy Docker container on EC2') {
steps {
script {
sshagent(['aws-ssh']) {
sh "ssh -o StrictHostKeyChecking=no ec2-user@35.157.110.150 'xgs.buildEC2()'"
}
}
}
}
jenkins.groovy script
def buildEC2() {
// Check if container exists
def containerId = sh(script: "docker ps --quiet --filter name=$CONTAINER_NAME", returnStdout: true).trim()
if (containerId.isEmpty()) {
echo "Container $CONTAINER_NAME not found. Skipping stop/remove steps."
} else {
echo "Stopping and removing existing container $CONTAINER_NAME ..."
sh "docker stop $CONTAINER_NAME"
sh "docker rm $CONTAINER_NAME"
sh "docker rmi $DOCKERH_REPO/$IMAGE_TAG:latest" // Remove leftover image if needed
sh "docker rmi $DOCKERH_REPO/$IMAGE_TAG:$BUILD_VERSION" // Remove leftover image if needed
}
// Always run the container regardless of previous existence
echo "Starting container $CONTAINER_NAME ..."
sh "$DOCKER_RUN"
sh "docker image prune --force"
}
return this
Just deploying the container works good (executing commands like docker run with params etc).
What I fail to achieve is running the same logic from the former stage on the remote EC2 by defining the containerId
variable first and running a conditional statement. I get this error:
bash: -c: line 1: syntax error near unexpected token `('
bash: -c: line 1: `def containerId = sh(script: \"docker ps --quiet --filter name=$CONTAINER_NAME\", returnStdout: true).trim()'
I tried encapsulating with single quotes and escaping but it did not work or my lack of knowledge hinders me to understand the right approach.
Any help would be much appreciated.
p.s. I am new to the SE world and still learning.
After further tinkering I changed the logic and resorted to a workaround by simply executing a wget command in the jenkins file, which pulls a bash script from git and executes all needed commands.
Not really a direct answer to the question, but bottom line enables what I wanted to achieve. I also simplified the commands by utilizing docker-compose.
Jenkins stage:
stage('Deploy Docker container on EC2') {
steps {
script {
sshagent(['aws-ssh']) {
echo "Deploying Docker container on EC2 ..."
sh "ssh -o StrictHostKeyChecking=no ec2-user@35.157.110.150 'bash -c \"\$(wget -qLO - https://raw.githubusercontent.com/juronja/DiluteRight/refs/heads/main/ec2-commands.sh)\"'"
}
}
}
}
bash script:
#!/bin/bash
# Downloading and overwriting the compose file
wget -O compose.yaml https://raw.githubusercontent.com/juronja/DiluteRight/refs/heads/main/compose.yaml
# Stoping and starting the container
docker-compose down
docker-compose up -d